backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / packet / sctp.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
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 #    http://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
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import abc
17 import six
18 import struct
19
20 from ryu.lib import addrconv
21 from ryu.lib import stringify
22 from ryu.lib.packet import packet_base
23
24 # Chunk Types
25 TYPE_DATA = 0
26 TYPE_INIT = 1
27 TYPE_INIT_ACK = 2
28 TYPE_SACK = 3
29 TYPE_HEARTBEAT = 4
30 TYPE_HEARTBEAT_ACK = 5
31 TYPE_ABORT = 6
32 TYPE_SHUTDOWN = 7
33 TYPE_SHUTDOWN_ACK = 8
34 TYPE_ERROR = 9
35 TYPE_COOKIE_ECHO = 10
36 TYPE_COOKIE_ACK = 11
37 TYPE_ECN_ECHO = 12
38 TYPE_CWR = 13
39 TYPE_SHUTDOWN_COMPLETE = 14
40
41 # Cause Code
42 CCODE_INVALID_STREAM_ID = 1
43 CCODE_MISSING_PARAM = 2
44 CCODE_STALE_COOKIE = 3
45 CCODE_OUT_OF_RESOURCE = 4
46 CCODE_UNRESOLVABLE_ADDR = 5
47 CCODE_UNRECOGNIZED_CHUNK = 6
48 CCODE_INVALID_PARAM = 7
49 CCODE_UNRECOGNIZED_PARAM = 8
50 CCODE_NO_USERDATA = 9
51 CCODE_COOKIE_WHILE_SHUTDOWN = 10
52 CCODE_RESTART_WITH_NEW_ADDR = 11
53 CCODE_USER_INITIATED_ABORT = 12
54 CCODE_PROTOCOL_VIOLATION = 13
55
56 # Chunk Parameter Types
57 PTYPE_HEARTBEAT = 1
58 PTYPE_IPV4 = 5
59 PTYPE_IPV6 = 6
60 PTYPE_STATE_COOKIE = 7
61 PTYPE_UNRECOGNIZED_PARAM = 8
62 PTYPE_COOKIE_PRESERVE = 9
63 PTYPE_HOST_ADDR = 11
64 PTYPE_SUPPORTED_ADDR = 12
65 PTYPE_ECN = 32768
66
67
68 class sctp(packet_base.PacketBase):
69     """Stream Control Transmission Protocol (SCTP)
70     header encoder/decoder class (RFC 4960).
71
72     An instance has the following attributes at least.
73     Most of them are same to the on-wire counterparts but in host byte order.
74     __init__ takes the corresponding args in this order.
75
76     .. tabularcolumns:: |l|L|
77
78     ============== =====================================================
79     Attribute      Description
80     ============== =====================================================
81     src_port       Source Port
82     dst_port       Destination Port
83     vtag           Verification Tag
84     csum           Checksum
85                    (0 means automatically-calculate when encoding)
86     chunks         a list of derived classes of ryu.lib.packet.sctp.chunk.
87     ============== =====================================================
88     """
89
90     _PACK_STR = '!HHII'
91     _MIN_LEN = struct.calcsize(_PACK_STR)
92     _SCTP_CHUNK_TYPE = {}
93     _class_prefixes = ['chunk_']
94
95     @staticmethod
96     def register_chunk_type(*args):
97         def _register_chunk_type(cls):
98             sctp._SCTP_CHUNK_TYPE[cls.chunk_type()] = cls
99             return cls
100         return _register_chunk_type(args[0])
101
102     def __init__(self, src_port=1, dst_port=1, vtag=0, csum=0, chunks=None):
103         super(sctp, self).__init__()
104         self.src_port = src_port
105         self.dst_port = dst_port
106         self.vtag = vtag
107         self.csum = csum
108         chunks = chunks or []
109         assert isinstance(chunks, list)
110         for one in chunks:
111             assert isinstance(one, chunk)
112         self.chunks = chunks
113
114     @classmethod
115     def parser(cls, buf):
116         (src_port, dst_port, vtag, csum) = struct.unpack_from(
117             cls._PACK_STR, buf)
118         chunks = []
119         offset = cls._MIN_LEN
120         while offset < len(buf):
121             (type_, ) = struct.unpack_from('!B', buf, offset)
122             cls_ = cls._SCTP_CHUNK_TYPE.get(type_)
123             if not cls_:
124                 break
125             ins = cls_.parser(buf[offset:])
126             chunks.append(ins)
127             offset += len(ins)
128         msg = cls(src_port, dst_port, vtag, csum, chunks)
129         return msg, None, buf[offset:]
130
131     def serialize(self, payload, prev):
132         buf = bytearray(struct.pack(
133             self._PACK_STR, self.src_port, self.dst_port, self.vtag,
134             self.csum))
135         if self.chunks:
136             for one in self.chunks:
137                 buf.extend(one.serialize())
138         if self.csum == 0:
139             self.csum = self._checksum(buf)
140             struct.pack_into('!I', buf, 8, self.csum)
141         return six.binary_type(buf)
142
143     def __len__(self):
144         length = self._MIN_LEN
145         if self.chunks is not None:
146             for one in self.chunks:
147                 length += len(one)
148         return length
149
150     def _checksum(self, data):
151         # from RFC 3309
152         crc_c = [
153             0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
154             0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
155             0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
156             0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
157             0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
158             0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
159             0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
160             0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
161             0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
162             0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
163             0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
164             0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
165             0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
166             0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
167             0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
168             0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
169             0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
170             0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
171             0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
172             0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
173             0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
174             0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
175             0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
176             0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
177             0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
178             0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
179             0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
180             0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
181             0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
182             0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
183             0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
184             0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
185             0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
186             0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
187             0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
188             0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
189             0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
190             0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
191             0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
192             0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
193             0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
194             0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
195             0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
196             0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
197             0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
198             0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
199             0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
200             0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
201             0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
202             0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
203             0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
204             0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
205             0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
206             0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
207             0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
208             0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
209             0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
210             0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
211             0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
212             0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
213             0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
214             0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
215             0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
216             0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
217         ]
218
219         crc32 = 0xffffffff
220         for c in str(data):
221             crc32 = (crc32 >> 8) ^ crc_c[(crc32 ^ (ord(c))) & 0xFF]
222         crc32 = (~crc32) & 0xffffffff
223         return struct.unpack(">I", struct.pack("<I", crc32))[0]
224
225
226 # =======================================================================
227 #
228 # Chunk Types
229 #
230 # =======================================================================
231 @six.add_metaclass(abc.ABCMeta)
232 class chunk(stringify.StringifyMixin):
233     _PACK_STR = '!BBH'
234     _MIN_LEN = struct.calcsize(_PACK_STR)
235
236     @classmethod
237     @abc.abstractmethod
238     def chunk_type(cls):
239         pass
240
241     @abc.abstractmethod
242     def __init__(self, type_, length):
243         self._type = type_
244         self.length = length
245
246     @classmethod
247     @abc.abstractmethod
248     def parser(cls, buf):
249         pass
250
251     def __len__(self):
252         return self.length
253
254
255 @six.add_metaclass(abc.ABCMeta)
256 class chunk_init_base(chunk):
257     _PACK_STR = '!BBHIIHHI'
258     _MIN_LEN = struct.calcsize(_PACK_STR)
259     _class_prefixes = ['param_']
260
261     def __init__(self, flags=0, length=0, init_tag=0, a_rwnd=0, os=0,
262                  mis=0, i_tsn=0, params=None):
263         super(chunk_init_base, self).__init__(self.chunk_type(), length)
264         self.flags = flags
265         self.init_tag = init_tag
266         self.a_rwnd = a_rwnd
267         self.os = os
268         self.mis = mis
269         self.i_tsn = i_tsn
270         params = params or []
271         assert isinstance(params, list)
272         for one in params:
273             assert isinstance(one, param)
274         self.params = params
275
276     @classmethod
277     def parser_base(cls, buf, recog):
278         (_, flags, length, init_tag, a_rwnd, os, mis, i_tsn
279          ) = struct.unpack_from(cls._PACK_STR, buf)
280         params = []
281         offset = cls._MIN_LEN
282         while offset < length:
283             (ptype, ) = struct.unpack_from('!H', buf, offset)
284             cls_ = recog.get(ptype)
285             if not cls_:
286                 break
287             ins = cls_.parser(buf[offset:])
288             params.append(ins)
289             offset += len(ins)
290         msg = cls(flags, length, init_tag, a_rwnd, os, mis, i_tsn, params)
291         return msg
292
293     def serialize(self):
294         buf = bytearray(struct.pack(
295             self._PACK_STR, self.chunk_type(), self.flags,
296             self.length, self.init_tag, self.a_rwnd, self.os, self.mis,
297             self.i_tsn))
298         for one in self.params:
299             buf.extend(one.serialize())
300         if 0 == self.length:
301             self.length = len(buf)
302             struct.pack_into('!H', buf, 2, self.length)
303         return six.binary_type(buf)
304
305
306 @six.add_metaclass(abc.ABCMeta)
307 class chunk_heartbeat_base(chunk):
308     _class_prefixes = ['param_']
309
310     def __init__(self, flags=0, length=0, info=None):
311         super(chunk_heartbeat_base, self).__init__(
312             self.chunk_type(), length)
313         self.flags = flags
314         if info is not None:
315             assert isinstance(info, param)
316         self.info = info
317
318     @classmethod
319     def parser_base(cls, buf, recog):
320         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
321         (ptype, ) = struct.unpack_from('!H', buf, cls._MIN_LEN)
322         cls_ = recog.get(ptype)
323         info = cls_.parser(buf[cls._MIN_LEN:])
324         msg = cls(flags, length, info)
325         return msg
326
327     def serialize(self):
328         buf = bytearray(struct.pack(
329             self._PACK_STR, self.chunk_type(), self.flags,
330             self.length))
331         if self.info is not None:
332             buf.extend(self.info.serialize())
333         if 0 == self.length:
334             self.length = len(buf)
335             struct.pack_into('!H', buf, 2, self.length)
336         return six.binary_type(buf)
337
338
339 @six.add_metaclass(abc.ABCMeta)
340 class chunk_ack_base(chunk):
341     def __init__(self, flags=0, length=0):
342         super(chunk_ack_base, self).__init__(self.chunk_type(), length)
343         self.flags = flags
344
345     @classmethod
346     def parser(cls, buf):
347         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
348         return cls(flags, length)
349
350     def serialize(self):
351         if 0 == self.length:
352             self.length = self._MIN_LEN
353         buf = struct.pack(
354             self._PACK_STR, self.chunk_type(), self.flags,
355             self.length)
356         return buf
357
358
359 @six.add_metaclass(abc.ABCMeta)
360 class chunk_ecn_base(chunk):
361     _PACK_STR = '!BBHI'
362     _MIN_LEN = struct.calcsize(_PACK_STR)
363
364     def __init__(self, flags=0, length=0, low_tsn=0):
365         super(chunk_ecn_base, self).__init__(self.chunk_type(), length)
366         self.flags = flags
367         self.low_tsn = low_tsn
368
369     @classmethod
370     def parser(cls, buf):
371         (_, flags, length, low_tsn) = struct.unpack_from(cls._PACK_STR, buf)
372         return cls(flags, length, low_tsn)
373
374     def serialize(self):
375         if 0 == self.length:
376             self.length = self._MIN_LEN
377         buf = struct.pack(
378             self._PACK_STR, self.chunk_type(), self.flags, self.length,
379             self.low_tsn)
380         return buf
381
382
383 @sctp.register_chunk_type
384 class chunk_data(chunk):
385     """Stream Control Transmission Protocol (SCTP)
386     sub encoder/decoder class for Payload Data (DATA) chunk (RFC 4960).
387
388     This class is used with the following.
389
390     - ryu.lib.packet.sctp.sctp
391
392     An instance has the following attributes at least.
393     Most of them are same to the on-wire counterparts but in host byte order.
394     __init__ takes the corresponding args in this order.
395
396     .. tabularcolumns:: |l|L|
397
398     ============== =====================================================
399     Attribute      Description
400     ============== =====================================================
401     unordered      if set to '1', the receiver ignores the sequence number.
402     begin          if set to '1', this chunk is the first fragment.
403     end            if set to '1', this chunk is the last fragment.
404     length         length of this chunk containing this header.
405                    (0 means automatically-calculate when encoding)
406     tsn            Transmission Sequence Number.
407     sid            stream id.
408     seq            the sequence number.
409     payload_id     application specified protocol id. '0' means that
410                    no application id is identified.
411     payload_data   user data.
412     ============== =====================================================
413     """
414
415     _PACK_STR = '!BBHIHHI'
416     _MIN_LEN = struct.calcsize(_PACK_STR)
417
418     @classmethod
419     def chunk_type(cls):
420         return TYPE_DATA
421
422     def __init__(self, unordered=0, begin=0, end=0, length=0, tsn=0,
423                  sid=0, seq=0, payload_id=0, payload_data=None):
424         assert (1 == unordered | 1)
425         assert (1 == begin | 1)
426         assert (1 == end | 1)
427         assert (payload_data is not None)
428         super(chunk_data, self).__init__(self.chunk_type(), length)
429         self.unordered = unordered
430         self.begin = begin
431         self.end = end
432         self.tsn = tsn
433         self.sid = sid
434         self.seq = seq
435         self.payload_id = payload_id
436         self.payload_data = payload_data
437
438     @classmethod
439     def parser(cls, buf):
440         (_, flags, length, tsn, sid, seq, payload_id
441          ) = struct.unpack_from(cls._PACK_STR, buf)
442         unordered = (flags >> 2) & 1
443         begin = (flags >> 1) & 1
444         end = (flags >> 0) & 1
445         fmt = '!%ds' % (length - cls._MIN_LEN)
446         (payload_data, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
447         return cls(unordered, begin, end, length, tsn, sid, seq,
448                    payload_id, payload_data)
449
450     def serialize(self):
451         flags = (
452             (self.unordered << 2) |
453             (self.begin << 1) |
454             (self.end << 0))
455         buf = bytearray(struct.pack(
456             self._PACK_STR, self.chunk_type(), flags, self.length,
457             self.tsn, self.sid, self.seq, self.payload_id))
458         buf.extend(self.payload_data)
459         if 0 == self.length:
460             self.length = len(buf)
461             struct.pack_into('!H', buf, 2, self.length)
462         return six.binary_type(buf)
463
464
465 @sctp.register_chunk_type
466 class chunk_init(chunk_init_base):
467     """Stream Control Transmission Protocol (SCTP)
468     sub encoder/decoder class for Initiation (INIT) chunk (RFC 4960).
469
470     This class is used with the following.
471
472     - ryu.lib.packet.sctp.sctp
473
474     An instance has the following attributes at least.
475     Most of them are same to the on-wire counterparts but in host byte order.
476     __init__ takes the corresponding args in this order.
477
478     .. tabularcolumns:: |l|L|
479
480     ============== =====================================================
481     Attribute      Description
482     ============== =====================================================
483     flags          set to '0'. this field will be ignored.
484     length         length of this chunk containing this header.
485                    (0 means automatically-calculate when encoding)
486     init_tag       the tag that be used as Verification Tag.
487     a_rwnd         Advertised Receiver Window Credit.
488     os             number of outbound streams.
489     mis            number of inbound streams.
490     i_tsn          Transmission Sequence Number that the sender will use.
491     params         Optional/Variable-Length Parameters.
492
493                    a list of derived classes of ryu.lib.packet.sctp.param.
494     ============== =====================================================
495     """
496
497     _RECOGNIZED_PARAMS = {}
498
499     @staticmethod
500     def register_param_type(*args):
501         def _register_param_type(cls):
502             chunk_init._RECOGNIZED_PARAMS[cls.param_type()] = cls
503             return cls
504         return _register_param_type(args[0])
505
506     @classmethod
507     def chunk_type(cls):
508         return TYPE_INIT
509
510     @classmethod
511     def parser(cls, buf):
512         return super(chunk_init, cls).parser_base(
513             buf, cls._RECOGNIZED_PARAMS)
514
515
516 @sctp.register_chunk_type
517 class chunk_init_ack(chunk_init_base):
518     """Stream Control Transmission Protocol (SCTP)
519     sub encoder/decoder class for Initiation Acknowledgement (INIT ACK)
520     chunk (RFC 4960).
521
522     This class is used with the following.
523
524     - ryu.lib.packet.sctp.sctp
525
526     An instance has the following attributes at least.
527     Most of them are same to the on-wire counterparts but in host byte order.
528     __init__ takes the corresponding args in this order.
529
530     .. tabularcolumns:: |l|L|
531
532     ============== =====================================================
533     Attribute      Description
534     ============== =====================================================
535     flags          set to '0'. this field will be ignored.
536     length         length of this chunk containing this header.
537                    (0 means automatically-calculate when encoding)
538     init_tag       the tag that be used as Verification Tag.
539     a_rwnd         Advertised Receiver Window Credit.
540     os             number of outbound streams.
541     mis            number of inbound streams.
542     i_tsn          Transmission Sequence Number that the sender will use.
543     params         Optional/Variable-Length Parameters.
544
545                    a list of derived classes of ryu.lib.packet.sctp.param.
546     ============== =====================================================
547     """
548
549     _RECOGNIZED_PARAMS = {}
550
551     @staticmethod
552     def register_param_type(*args):
553         def _register_param_type(cls):
554             chunk_init_ack._RECOGNIZED_PARAMS[cls.param_type()] = cls
555             return cls
556         return _register_param_type(args[0])
557
558     @classmethod
559     def chunk_type(cls):
560         return TYPE_INIT_ACK
561
562     @classmethod
563     def parser(cls, buf):
564         return super(chunk_init_ack, cls).parser_base(
565             buf, cls._RECOGNIZED_PARAMS)
566
567
568 @sctp.register_chunk_type
569 class chunk_sack(chunk):
570     """Stream Control Transmission Protocol (SCTP)
571     sub encoder/decoder class for Selective Acknowledgement (SACK) chunk
572     (RFC 4960).
573
574     This class is used with the following.
575
576     - ryu.lib.packet.sctp.sctp
577
578     An instance has the following attributes at least.
579     Most of them are same to the on-wire counterparts but in host byte order.
580     __init__ takes the corresponding args in this order.
581
582     .. tabularcolumns:: |l|L|
583
584     ============== =====================================================
585     Attribute      Description
586     ============== =====================================================
587     flags          set to '0'. this field will be ignored.
588     length         length of this chunk containing this header.
589                    (0 means automatically-calculate when encoding)
590     tsn_ack        TSN of the last DATA chunk received in sequence
591                    before a gap.
592     a_rwnd         Advertised Receiver Window Credit.
593     gapack_num     number of Gap Ack blocks.
594     duptsn_num     number of duplicate TSNs.
595     gapacks        a list of Gap Ack blocks. one block is made of a list
596                    with the start offset and the end offset from tsn_ack.
597                    e.g.) gapacks = [[2, 3], [10, 12], [19, 21]]
598     duptsns        a list of duplicate TSN.
599     ============== =====================================================
600     """
601
602     _PACK_STR = '!BBHIIHH'
603     _MIN_LEN = struct.calcsize(_PACK_STR)
604     _GAPACK_STR = '!HH'
605     _GAPACK_LEN = struct.calcsize(_GAPACK_STR)
606     _DUPTSN_STR = '!I'
607     _DUPTSN_LEN = struct.calcsize(_DUPTSN_STR)
608
609     @classmethod
610     def chunk_type(cls):
611         return TYPE_SACK
612
613     def __init__(self, flags=0, length=0, tsn_ack=0, a_rwnd=0,
614                  gapack_num=0, duptsn_num=0, gapacks=None, duptsns=None):
615         super(chunk_sack, self).__init__(self.chunk_type(), length)
616         self.flags = flags
617         self.tsn_ack = tsn_ack
618         self.a_rwnd = a_rwnd
619         self.gapack_num = gapack_num
620         self.duptsn_num = duptsn_num
621         gapacks = gapacks or []
622         assert isinstance(gapacks, list)
623         for one in gapacks:
624             assert isinstance(one, list)
625             assert 2 == len(one)
626         self.gapacks = gapacks
627         duptsns = duptsns or []
628         assert isinstance(duptsns, list)
629         self.duptsns = duptsns
630
631     @classmethod
632     def parser(cls, buf):
633         (_, flags, length, tsn_ack, a_rwnd, gapack_num, duptsn_num
634          ) = struct.unpack_from(cls._PACK_STR, buf)
635         gapacks = []
636         offset = cls._MIN_LEN
637         for _ in range(gapack_num):
638             (gapack_start, gapack_end) = struct.unpack_from(
639                 cls._GAPACK_STR, buf, offset)
640             gapacks.append([gapack_start, gapack_end])
641             offset += cls._GAPACK_LEN
642         duptsns = []
643         for _ in range(duptsn_num):
644             (duptsn, ) = struct.unpack_from(cls._DUPTSN_STR, buf, offset)
645             duptsns.append(duptsn)
646             offset += cls._DUPTSN_LEN
647         return cls(flags, length, tsn_ack, a_rwnd, gapack_num, duptsn_num,
648                    gapacks, duptsns)
649
650     def serialize(self):
651         buf = bytearray(struct.pack(
652             self._PACK_STR, self.chunk_type(), self.flags,
653             self.length, self.tsn_ack, self.a_rwnd, self.gapack_num,
654             self.duptsn_num))
655         for one in self.gapacks:
656             buf.extend(struct.pack(chunk_sack._GAPACK_STR, one[0], one[1]))
657         for one in self.duptsns:
658             buf.extend(struct.pack(chunk_sack._DUPTSN_STR, one))
659         if 0 == self.length:
660             self.length = len(buf)
661             struct.pack_into('!H', buf, 2, self.length)
662         return six.binary_type(buf)
663
664
665 @sctp.register_chunk_type
666 class chunk_heartbeat(chunk_heartbeat_base):
667     """Stream Control Transmission Protocol (SCTP)
668     sub encoder/decoder class for Heartbeat Request (HEARTBEAT) chunk
669     (RFC 4960).
670
671     This class is used with the following.
672
673     - ryu.lib.packet.sctp.sctp
674
675     An instance has the following attributes at least.
676     Most of them are same to the on-wire counterparts but in host byte order.
677     __init__ takes the corresponding args in this order.
678
679     .. tabularcolumns:: |l|L|
680
681     ============== =====================================================
682     Attribute      Description
683     ============== =====================================================
684     flags          set to '0'. this field will be ignored.
685     length         length of this chunk containing this header.
686                    (0 means automatically-calculate when encoding)
687     info           ryu.lib.packet.sctp.param_heartbeat.
688     ============== =====================================================
689     """
690
691     _RECOGNIZED_PARAMS = {}
692
693     @staticmethod
694     def register_param_type(*args):
695         def _register_param_type(cls):
696             chunk_heartbeat._RECOGNIZED_PARAMS[cls.param_type()] = cls
697             return cls
698         return _register_param_type(args[0])
699
700     @classmethod
701     def chunk_type(cls):
702         return TYPE_HEARTBEAT
703
704     @classmethod
705     def parser(cls, buf):
706         return super(chunk_heartbeat, cls).parser_base(
707             buf, cls._RECOGNIZED_PARAMS)
708
709
710 @sctp.register_chunk_type
711 class chunk_heartbeat_ack(chunk_heartbeat_base):
712     """Stream Control Transmission Protocol (SCTP)
713     sub encoder/decoder class for Heartbeat Acknowledgement
714     (HEARTBEAT ACK) chunk (RFC 4960).
715
716     This class is used with the following.
717
718     - ryu.lib.packet.sctp.sctp
719
720     An instance has the following attributes at least.
721     Most of them are same to the on-wire counterparts but in host byte order.
722     __init__ takes the corresponding args in this order.
723
724     .. tabularcolumns:: |l|L|
725
726     ============== =====================================================
727     Attribute      Description
728     ============== =====================================================
729     flags          set to '0'. this field will be ignored.
730     length         length of this chunk containing this header.
731                    (0 means automatically-calculate when encoding)
732     info           ryu.lib.packet.sctp.param_heartbeat.
733     ============== =====================================================
734     """
735
736     _RECOGNIZED_PARAMS = {}
737
738     @staticmethod
739     def register_param_type(*args):
740         def _register_param_type(cls):
741             chunk_heartbeat_ack._RECOGNIZED_PARAMS[cls.param_type()] = cls
742             return cls
743         return _register_param_type(args[0])
744
745     @classmethod
746     def chunk_type(cls):
747         return TYPE_HEARTBEAT_ACK
748
749     @classmethod
750     def parser(cls, buf):
751         return super(chunk_heartbeat_ack, cls).parser_base(
752             buf, cls._RECOGNIZED_PARAMS)
753
754
755 @sctp.register_chunk_type
756 class chunk_abort(chunk):
757     """Stream Control Transmission Protocol (SCTP)
758     sub encoder/decoder class for Abort Association (ABORT) chunk (RFC 4960).
759
760     This class is used with the following.
761
762     - ryu.lib.packet.sctp.sctp
763
764     An instance has the following attributes at least.
765     Most of them are same to the on-wire counterparts but in host byte order.
766     __init__ takes the corresponding args in this order.
767
768     .. tabularcolumns:: |l|L|
769
770     ============== =====================================================
771     Attribute      Description
772     ============== =====================================================
773     tflag          '0' means the Verification tag is normal. '1' means
774                    the Verification tag is copy of the sender.
775     length         length of this chunk containing this header.
776                    (0 means automatically-calculate when encoding)
777     causes         a list of derived classes of ryu.lib.packet.sctp.causes.
778     ============== =====================================================
779     """
780
781     _class_prefixes = ['cause_']
782     _RECOGNIZED_CAUSES = {}
783
784     @staticmethod
785     def register_cause_code(*args):
786         def _register_cause_code(cls):
787             chunk_abort._RECOGNIZED_CAUSES[cls.cause_code()] = cls
788             return cls
789         return _register_cause_code(args[0])
790
791     @classmethod
792     def chunk_type(cls):
793         return TYPE_ABORT
794
795     def __init__(self, tflag=0, length=0, causes=None):
796         super(chunk_abort, self).__init__(self.chunk_type(), length)
797         assert (1 == tflag | 1)
798         self.tflag = tflag
799         causes = causes or []
800         assert isinstance(causes, list)
801         for one in causes:
802             assert isinstance(one, cause)
803         self.causes = causes
804
805     @classmethod
806     def parser(cls, buf):
807         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
808         tflag = (flags >> 0) & 1
809         causes = []
810         offset = cls._MIN_LEN
811         while offset < length:
812             (ccode, ) = struct.unpack_from('!H', buf, offset)
813             cls_ = cls._RECOGNIZED_CAUSES.get(ccode)
814             if not cls_:
815                 break
816             ins = cls_.parser(buf[offset:])
817             causes.append(ins)
818             offset += len(ins)
819         return cls(tflag, length, causes)
820
821     def serialize(self):
822         flags = (self.tflag << 0)
823         buf = bytearray(struct.pack(
824             self._PACK_STR, self.chunk_type(), flags, self.length))
825         for one in self.causes:
826             buf.extend(one.serialize())
827         if 0 == self.length:
828             self.length = len(buf)
829             struct.pack_into('!H', buf, 2, self.length)
830         return six.binary_type(buf)
831
832
833 @sctp.register_chunk_type
834 class chunk_shutdown(chunk):
835     """Stream Control Transmission Protocol (SCTP)
836     sub encoder/decoder class for Shutdown Association (SHUTDOWN) chunk
837     (RFC 4960).
838
839     This class is used with the following.
840
841     - ryu.lib.packet.sctp.sctp
842
843     An instance has the following attributes at least.
844     Most of them are same to the on-wire counterparts but in host byte order.
845     __init__ takes the corresponding args in this order.
846
847     .. tabularcolumns:: |l|L|
848
849     ============== =====================================================
850     Attribute      Description
851     ============== =====================================================
852     flags          set to '0'. this field will be ignored.
853     length         length of this chunk containing this header.
854                    (0 means automatically-calculate when encoding)
855     tsn_ack        TSN of the last DATA chunk received in sequence
856                    before a gap.
857     ============== =====================================================
858     """
859
860     _PACK_STR = '!BBHI'
861     _MIN_LEN = struct.calcsize(_PACK_STR)
862
863     @classmethod
864     def chunk_type(cls):
865         return TYPE_SHUTDOWN
866
867     def __init__(self, flags=0, length=0, tsn_ack=0):
868         super(chunk_shutdown, self).__init__(self.chunk_type(), length)
869         self.flags = flags
870         self.tsn_ack = tsn_ack
871
872     @classmethod
873     def parser(cls, buf):
874         (_, flags, length, tsn_ack
875          ) = struct.unpack_from(cls._PACK_STR, buf)
876         msg = cls(flags, length, tsn_ack)
877         return msg
878
879     def serialize(self):
880         if 0 == self.length:
881             self.length = self._MIN_LEN
882         buf = struct.pack(
883             self._PACK_STR, self.chunk_type(), self.flags,
884             self.length, self.tsn_ack)
885         return buf
886
887
888 @sctp.register_chunk_type
889 class chunk_shutdown_ack(chunk_ack_base):
890     """Stream Control Transmission Protocol (SCTP)
891     sub encoder/decoder class for Shutdown Acknowledgement (SHUTDOWN ACK)
892     chunk (RFC 4960).
893
894     This class is used with the following.
895
896     - ryu.lib.packet.sctp.sctp
897
898     An instance has the following attributes at least.
899     Most of them are same to the on-wire counterparts but in host byte order.
900     __init__ takes the corresponding args in this order.
901
902     .. tabularcolumns:: |l|L|
903
904     ============== =====================================================
905     Attribute      Description
906     ============== =====================================================
907     flags          set to '0'. this field will be ignored.
908     length         length of this chunk containing this header.
909                    (0 means automatically-calculate when encoding)
910     ============== =====================================================
911     """
912
913     @classmethod
914     def chunk_type(cls):
915         return TYPE_SHUTDOWN_ACK
916
917
918 @sctp.register_chunk_type
919 class chunk_error(chunk):
920     """Stream Control Transmission Protocol (SCTP)
921     sub encoder/decoder class for Operation Error (ERROR) chunk (RFC 4960).
922
923     This class is used with the following.
924
925     - ryu.lib.packet.sctp.sctp
926
927     An instance has the following attributes at least.
928     Most of them are same to the on-wire counterparts but in host byte order.
929     __init__ takes the corresponding args in this order.
930
931     .. tabularcolumns:: |l|L|
932
933     ============== =====================================================
934     Attribute      Description
935     ============== =====================================================
936     flags          set to '0'. this field will be ignored.
937     length         length of this chunk containing this header.
938                    (0 means automatically-calculate when encoding)
939     causes         a list of derived classes of ryu.lib.packet.sctp.causes.
940     ============== =====================================================
941     """
942
943     _class_prefixes = ['cause_']
944     _RECOGNIZED_CAUSES = {}
945
946     @staticmethod
947     def register_cause_code(*args):
948         def _register_cause_code(cls):
949             chunk_error._RECOGNIZED_CAUSES[cls.cause_code()] = cls
950             return cls
951         return _register_cause_code(args[0])
952
953     @classmethod
954     def chunk_type(cls):
955         return TYPE_ERROR
956
957     def __init__(self, flags=0, length=0, causes=None):
958         super(chunk_error, self).__init__(self.chunk_type(), length)
959         self.flags = flags
960         causes = causes or []
961         assert isinstance(causes, list)
962         for one in causes:
963             assert isinstance(one, cause)
964         self.causes = causes
965
966     @classmethod
967     def parser(cls, buf):
968         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
969         causes = []
970         offset = cls._MIN_LEN
971         while offset < length:
972             (ccode, ) = struct.unpack_from('!H', buf, offset)
973             cls_ = cls._RECOGNIZED_CAUSES.get(ccode)
974             if not cls_:
975                 break
976             ins = cls_.parser(buf[offset:])
977             causes.append(ins)
978             offset += len(ins)
979         return cls(flags, length, causes)
980
981     def serialize(self):
982         buf = bytearray(struct.pack(
983             self._PACK_STR, self.chunk_type(), self.flags, self.length))
984         for one in self.causes:
985             buf.extend(one.serialize())
986         if 0 == self.length:
987             self.length = len(buf)
988             struct.pack_into('!H', buf, 2, self.length)
989         return six.binary_type(buf)
990
991
992 @sctp.register_chunk_type
993 class chunk_cookie_echo(chunk):
994     """Stream Control Transmission Protocol (SCTP)
995     sub encoder/decoder class for Cookie Echo (COOKIE ECHO) chunk (RFC 4960).
996
997     This class is used with the following.
998
999     - ryu.lib.packet.sctp.sctp
1000
1001     An instance has the following attributes at least.
1002     Most of them are same to the on-wire counterparts but in host byte order.
1003     __init__ takes the corresponding args in this order.
1004
1005     .. tabularcolumns:: |l|L|
1006
1007     ============== =====================================================
1008     Attribute      Description
1009     ============== =====================================================
1010     flags          set to '0'. this field will be ignored.
1011     length         length of this chunk containing this header.
1012                    (0 means automatically-calculate when encoding)
1013     cookie         cookie data.
1014     ============== =====================================================
1015     """
1016
1017     _PACK_STR = '!BBH'
1018     _MIN_LEN = struct.calcsize(_PACK_STR)
1019
1020     @classmethod
1021     def chunk_type(cls):
1022         return TYPE_COOKIE_ECHO
1023
1024     def __init__(self, flags=0, length=0, cookie=None):
1025         super(chunk_cookie_echo, self).__init__(self.chunk_type(), length)
1026         self.flags = flags
1027         self.cookie = cookie
1028
1029     @classmethod
1030     def parser(cls, buf):
1031         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
1032         _len = length - cls._MIN_LEN
1033         cookie = None
1034         if _len:
1035             fmt = '%ds' % _len
1036             (cookie, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
1037         return cls(flags, length, cookie)
1038
1039     def serialize(self):
1040         buf = bytearray(struct.pack(
1041             self._PACK_STR, self.chunk_type(), self.flags,
1042             self.length))
1043         if self.cookie is not None:
1044             buf.extend(self.cookie)
1045         if 0 == self.length:
1046             self.length = len(buf)
1047             struct.pack_into('!H', buf, 2, self.length)
1048         mod = len(buf) % 4
1049         if mod:
1050             buf.extend(bytearray(4 - mod))
1051         return six.binary_type(buf)
1052
1053
1054 @sctp.register_chunk_type
1055 class chunk_cookie_ack(chunk_ack_base):
1056     """Stream Control Transmission Protocol (SCTP)
1057     sub encoder/decoder class for Cookie Acknowledgement (COOKIE ACK)
1058     chunk (RFC 4960).
1059
1060     This class is used with the following.
1061
1062     - ryu.lib.packet.sctp.sctp
1063
1064     An instance has the following attributes at least.
1065     Most of them are same to the on-wire counterparts but in host byte order.
1066     __init__ takes the corresponding args in this order.
1067
1068     .. tabularcolumns:: |l|L|
1069
1070     ============== =====================================================
1071     Attribute      Description
1072     ============== =====================================================
1073     flags          set to '0'. this field will be ignored.
1074     length         length of this chunk containing this header.
1075                    (0 means automatically-calculate when encoding)
1076     ============== =====================================================
1077     """
1078
1079     @classmethod
1080     def chunk_type(cls):
1081         return TYPE_COOKIE_ACK
1082
1083
1084 @sctp.register_chunk_type
1085 class chunk_ecn_echo(chunk_ecn_base):
1086     """Stream Control Transmission Protocol (SCTP)
1087     sub encoder/decoder class for ECN-Echo chunk (RFC 4960 Appendix A.).
1088
1089     This class is used with the following.
1090
1091     - ryu.lib.packet.sctp.sctp
1092
1093     An instance has the following attributes at least.
1094     Most of them are same to the on-wire counterparts but in host byte order.
1095     __init__ takes the corresponding args in this order.
1096
1097     .. tabularcolumns:: |l|L|
1098
1099     ============== =====================================================
1100     Attribute      Description
1101     ============== =====================================================
1102     flags          set to '0'. this field will be ignored.
1103     length         length of this chunk containing this header.
1104                    (0 means automatically-calculate when encoding)
1105     low_tsn        the lowest TSN.
1106     ============== =====================================================
1107     """
1108
1109     @classmethod
1110     def chunk_type(cls):
1111         return TYPE_ECN_ECHO
1112
1113
1114 @sctp.register_chunk_type
1115 class chunk_cwr(chunk_ecn_base):
1116     """Stream Control Transmission Protocol (SCTP)
1117     sub encoder/decoder class for CWR chunk (RFC 4960 Appendix A.).
1118
1119     This class is used with the following.
1120
1121     - ryu.lib.packet.sctp.sctp
1122
1123     An instance has the following attributes at least.
1124     Most of them are same to the on-wire counterparts but in host byte order.
1125     __init__ takes the corresponding args in this order.
1126
1127     .. tabularcolumns:: |l|L|
1128
1129     ============== =====================================================
1130     Attribute      Description
1131     ============== =====================================================
1132     flags          set to '0'. this field will be ignored.
1133     length         length of this chunk containing this header.
1134                    (0 means automatically-calculate when encoding)
1135     low_tsn        the lowest TSN.
1136     ============== =====================================================
1137     """
1138
1139     @classmethod
1140     def chunk_type(cls):
1141         return TYPE_CWR
1142
1143
1144 @sctp.register_chunk_type
1145 class chunk_shutdown_complete(chunk):
1146     """Stream Control Transmission Protocol (SCTP)
1147     sub encoder/decoder class for Shutdown Complete (SHUTDOWN COMPLETE)
1148     chunk (RFC 4960).
1149
1150     This class is used with the following.
1151
1152     - ryu.lib.packet.sctp.sctp
1153
1154     An instance has the following attributes at least.
1155     Most of them are same to the on-wire counterparts but in host byte order.
1156     __init__ takes the corresponding args in this order.
1157
1158     .. tabularcolumns:: |l|L|
1159
1160     ============== =====================================================
1161     Attribute      Description
1162     ============== =====================================================
1163     tflag          '0' means the Verification tag is normal. '1' means
1164                    the Verification tag is copy of the sender.
1165     length         length of this chunk containing this header.
1166                    (0 means automatically-calculate when encoding)
1167     ============== =====================================================
1168     """
1169
1170     _PACK_STR = '!BBH'
1171     _MIN_LEN = struct.calcsize(_PACK_STR)
1172
1173     @classmethod
1174     def chunk_type(cls):
1175         return TYPE_SHUTDOWN_COMPLETE
1176
1177     def __init__(self, tflag=0, length=0):
1178         assert (1 == tflag | 1)
1179         super(chunk_shutdown_complete, self).__init__(
1180             self.chunk_type(), length)
1181         self.tflag = tflag
1182
1183     @classmethod
1184     def parser(cls, buf):
1185         (_, flags, length) = struct.unpack_from(cls._PACK_STR, buf)
1186         tflag = flags & 1
1187         msg = cls(tflag, length)
1188         return msg
1189
1190     def serialize(self):
1191         if 0 == self.length:
1192             self.length = self._MIN_LEN
1193         buf = struct.pack(
1194             self._PACK_STR, self.chunk_type(),
1195             self.tflag, self.length)
1196         return buf
1197
1198
1199 # =======================================================================
1200 #
1201 # Cause Code
1202 #
1203 # =======================================================================
1204 @six.add_metaclass(abc.ABCMeta)
1205 class cause(stringify.StringifyMixin):
1206     _PACK_STR = '!HH'
1207     _MIN_LEN = struct.calcsize(_PACK_STR)
1208
1209     @classmethod
1210     @abc.abstractmethod
1211     def cause_code(cls):
1212         pass
1213
1214     def __init__(self, length=0):
1215         self.length = length
1216
1217     @classmethod
1218     @abc.abstractmethod
1219     def parser(cls, buf):
1220         pass
1221
1222     def serialize(self):
1223         if 0 == self.length:
1224             self.length = self._MIN_LEN
1225         buf = struct.pack(
1226             self._PACK_STR, self.cause_code(), self.length)
1227         return buf
1228
1229     def __len__(self):
1230         length = self.length
1231         mod = length % 4
1232         if mod:
1233             length += 4 - mod
1234         return length
1235
1236
1237 @six.add_metaclass(abc.ABCMeta)
1238 class cause_with_value(cause):
1239     def __init__(self, value=None, length=0):
1240         super(cause_with_value, self).__init__(length)
1241         self.value = value
1242
1243     @classmethod
1244     def parser(cls, buf):
1245         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1246         value = None
1247         if (cls._MIN_LEN < length):
1248             fmt = '%ds' % (length - cls._MIN_LEN)
1249             (value, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
1250         return cls(value, length)
1251
1252     def serialize(self):
1253         buf = bytearray(struct.pack(
1254             self._PACK_STR, self.cause_code(), self.length))
1255         if self.value is not None:
1256             buf.extend(self.value)
1257         if 0 == self.length:
1258             self.length = len(buf)
1259             struct.pack_into('!H', buf, 2, self.length)
1260         mod = len(buf) % 4
1261         if mod:
1262             buf.extend(bytearray(4 - mod))
1263         return six.binary_type(buf)
1264
1265
1266 @chunk_abort.register_cause_code
1267 @chunk_error.register_cause_code
1268 class cause_invalid_stream_id(cause_with_value):
1269     """Stream Control Transmission Protocol (SCTP)
1270     sub encoder/decoder class for Invalid Stream Identifier (RFC 4960).
1271
1272     This class is used with the following.
1273
1274     - ryu.lib.packet.sctp.chunk_abort
1275     - ryu.lib.packet.sctp.chunk_error
1276
1277     An instance has the following attributes at least.
1278     Most of them are same to the on-wire counterparts but in host byte order.
1279     __init__ takes the corresponding args in this order.
1280
1281     .. tabularcolumns:: |l|L|
1282
1283     ============== =====================================================
1284     Attribute      Description
1285     ============== =====================================================
1286     value          stream id.
1287     length         length of this cause containing this header.
1288                    (0 means automatically-calculate when encoding)
1289     ============== =====================================================
1290     """
1291
1292     _PACK_STR = '!HHH2x'
1293     _MIN_LEN = struct.calcsize(_PACK_STR)
1294
1295     @classmethod
1296     def cause_code(cls):
1297         return CCODE_INVALID_STREAM_ID
1298
1299     def __init__(self, value=0, length=0):
1300         super(cause_invalid_stream_id, self).__init__(value, length)
1301
1302     @classmethod
1303     def parser(cls, buf):
1304         (_, length, value) = struct.unpack_from(cls._PACK_STR, buf)
1305         return cls(value, length)
1306
1307     def serialize(self):
1308         if 0 == self.length:
1309             self.length = self._MIN_LEN
1310         buf = struct.pack(
1311             self._PACK_STR, self.cause_code(), self.length, self.value)
1312         return buf
1313
1314
1315 @chunk_abort.register_cause_code
1316 @chunk_error.register_cause_code
1317 class cause_missing_param(cause):
1318     """Stream Control Transmission Protocol (SCTP)
1319     sub encoder/decoder class for Missing Mandatory Parameter (RFC 4960).
1320
1321     This class is used with the following.
1322
1323     - ryu.lib.packet.sctp.chunk_abort
1324     - ryu.lib.packet.sctp.chunk_error
1325
1326     An instance has the following attributes at least.
1327     Most of them are same to the on-wire counterparts but in host byte order.
1328     __init__ takes the corresponding args in this order.
1329
1330     .. tabularcolumns:: |l|L|
1331
1332     ============== =====================================================
1333     Attribute      Description
1334     ============== =====================================================
1335     types          a list of missing params.
1336     num            Number of missing params.
1337                    (0 means automatically-calculate when encoding)
1338     length         length of this cause containing this header.
1339                    (0 means automatically-calculate when encoding)
1340     ============== =====================================================
1341     """
1342
1343     _PACK_STR = '!HHI'
1344     _MIN_LEN = struct.calcsize(_PACK_STR)
1345
1346     @classmethod
1347     def cause_code(cls):
1348         return CCODE_MISSING_PARAM
1349
1350     def __init__(self, types=None, num=0, length=0):
1351         super(cause_missing_param, self).__init__(length)
1352         types = types or []
1353         assert isinstance(types, list)
1354         for one in types:
1355             assert isinstance(one, int)
1356         self.types = types
1357         self.num = num
1358
1359     @classmethod
1360     def parser(cls, buf):
1361         (_, length, num) = struct.unpack_from(cls._PACK_STR, buf)
1362         types = []
1363         offset = cls._MIN_LEN
1364         for count in range(num):
1365             offset = cls._MIN_LEN + (struct.calcsize('!H') * count)
1366             (one, ) = struct.unpack_from('!H', buf, offset)
1367             types.append(one)
1368         return cls(types, num, length)
1369
1370     def serialize(self):
1371         buf = bytearray(struct.pack(
1372             self._PACK_STR, self.cause_code(), self.length, self.num))
1373         for one in self.types:
1374             buf.extend(struct.pack('!H', one))
1375         if 0 == self.num:
1376             self.num = len(self.types)
1377             struct.pack_into('!I', buf, 4, self.num)
1378         if 0 == self.length:
1379             self.length = len(buf)
1380             struct.pack_into('!H', buf, 2, self.length)
1381         mod = len(buf) % 4
1382         if mod:
1383             buf.extend(bytearray(4 - mod))
1384         return six.binary_type(buf)
1385
1386
1387 @chunk_abort.register_cause_code
1388 @chunk_error.register_cause_code
1389 class cause_stale_cookie(cause_with_value):
1390     """Stream Control Transmission Protocol (SCTP)
1391     sub encoder/decoder class for Stale Cookie Error (RFC 4960).
1392
1393     This class is used with the following.
1394
1395     - ryu.lib.packet.sctp.chunk_abort
1396     - ryu.lib.packet.sctp.chunk_error
1397
1398     An instance has the following attributes at least.
1399     Most of them are same to the on-wire counterparts but in host byte order.
1400     __init__ takes the corresponding args in this order.
1401
1402     .. tabularcolumns:: |l|L|
1403
1404     ============== =====================================================
1405     Attribute      Description
1406     ============== =====================================================
1407     value          Measure of Staleness.
1408     length         length of this cause containing this header.
1409                    (0 means automatically-calculate when encoding)
1410     ============== =====================================================
1411     """
1412
1413     @classmethod
1414     def cause_code(cls):
1415         return CCODE_STALE_COOKIE
1416
1417
1418 @chunk_abort.register_cause_code
1419 @chunk_error.register_cause_code
1420 class cause_out_of_resource(cause):
1421     """Stream Control Transmission Protocol (SCTP)
1422     sub encoder/decoder class for Out of Resource (RFC 4960).
1423
1424     This class is used with the following.
1425
1426     - ryu.lib.packet.sctp.chunk_abort
1427     - ryu.lib.packet.sctp.chunk_error
1428
1429     An instance has the following attributes at least.
1430     Most of them are same to the on-wire counterparts but in host byte order.
1431     __init__ takes the corresponding args in this order.
1432
1433     .. tabularcolumns:: |l|L|
1434
1435     ============== =====================================================
1436     Attribute      Description
1437     ============== =====================================================
1438     length         length of this cause containing this header.
1439                    (0 means automatically-calculate when encoding)
1440     ============== =====================================================
1441     """
1442
1443     @classmethod
1444     def cause_code(cls):
1445         return CCODE_OUT_OF_RESOURCE
1446
1447     @classmethod
1448     def parser(cls, buf):
1449         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1450         return cls(length)
1451
1452
1453 @chunk_abort.register_cause_code
1454 @chunk_error.register_cause_code
1455 class cause_unresolvable_addr(cause_with_value):
1456     """Stream Control Transmission Protocol (SCTP)
1457     sub encoder/decoder class for Unresolvable Address (RFC 4960).
1458
1459     This class is used with the following.
1460
1461     - ryu.lib.packet.sctp.chunk_abort
1462     - ryu.lib.packet.sctp.chunk_error
1463
1464     An instance has the following attributes at least.
1465     Most of them are same to the on-wire counterparts but in host byte order.
1466     __init__ takes the corresponding args in this order.
1467
1468     .. tabularcolumns:: |l|L|
1469
1470     ============== =====================================================
1471     Attribute      Description
1472     ============== =====================================================
1473     value          Unresolvable Address. one of follows:
1474
1475                    ryu.lib.packet.sctp.param_host_addr,
1476
1477                    ryu.lib.packet.sctp.param_ipv4, or
1478
1479                    ryu.lib.packet.sctp.param_ipv6.
1480     length         length of this cause containing this header.
1481                    (0 means automatically-calculate when encoding)
1482     ============== =====================================================
1483     """
1484
1485     _class_prefixes = ['param_']
1486     _RECOGNIZED_PARAMS = {}
1487
1488     @staticmethod
1489     def register_param_type(*args):
1490         def _register_param_type(cls):
1491             cause_unresolvable_addr._RECOGNIZED_PARAMS[cls.param_type()] = cls
1492             return cls
1493         return _register_param_type(args[0])
1494
1495     @classmethod
1496     def cause_code(cls):
1497         return CCODE_UNRESOLVABLE_ADDR
1498
1499     @classmethod
1500     def parser(cls, buf):
1501         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1502         (ptype, ) = struct.unpack_from('!H', buf, cls._MIN_LEN)
1503         cls_ = cls._RECOGNIZED_PARAMS.get(ptype)
1504         value = cls_.parser(buf[cls._MIN_LEN:])
1505         return cls(value, length)
1506
1507     def serialize(self):
1508         buf = bytearray(struct.pack(
1509             self._PACK_STR, self.cause_code(), self.length))
1510         buf.extend(self.value.serialize())
1511         if 0 == self.length:
1512             self.length = len(buf)
1513             struct.pack_into('!H', buf, 2, self.length)
1514         mod = len(buf) % 4
1515         if mod:
1516             buf.extend(bytearray(4 - mod))
1517         return six.binary_type(buf)
1518
1519
1520 @chunk_abort.register_cause_code
1521 @chunk_error.register_cause_code
1522 class cause_unrecognized_chunk(cause_with_value):
1523     """Stream Control Transmission Protocol (SCTP)
1524     sub encoder/decoder class for Unrecognized Chunk Type (RFC 4960).
1525
1526     This class is used with the following.
1527
1528     - ryu.lib.packet.sctp.chunk_abort
1529     - ryu.lib.packet.sctp.chunk_error
1530
1531     An instance has the following attributes at least.
1532     Most of them are same to the on-wire counterparts but in host byte order.
1533     __init__ takes the corresponding args in this order.
1534
1535     .. tabularcolumns:: |l|L|
1536
1537     ============== =====================================================
1538     Attribute      Description
1539     ============== =====================================================
1540     value          Unrecognized Chunk.
1541     length         length of this cause containing this header.
1542                    (0 means automatically-calculate when encoding)
1543     ============== =====================================================
1544     """
1545
1546     @classmethod
1547     def cause_code(cls):
1548         return CCODE_UNRECOGNIZED_CHUNK
1549
1550
1551 @chunk_abort.register_cause_code
1552 @chunk_error.register_cause_code
1553 class cause_invalid_param(cause):
1554     """Stream Control Transmission Protocol (SCTP)
1555     sub encoder/decoder class for Invalid Mandatory Parameter (RFC 4960).
1556
1557     This class is used with the following.
1558
1559     - ryu.lib.packet.sctp.chunk_abort
1560     - ryu.lib.packet.sctp.chunk_error
1561
1562     An instance has the following attributes at least.
1563     Most of them are same to the on-wire counterparts but in host byte order.
1564     __init__ takes the corresponding args in this order.
1565
1566     .. tabularcolumns:: |l|L|
1567
1568     ============== =====================================================
1569     Attribute      Description
1570     ============== =====================================================
1571     length         length of this cause containing this header.
1572                    (0 means automatically-calculate when encoding)
1573     ============== =====================================================
1574     """
1575
1576     @classmethod
1577     def cause_code(cls):
1578         return CCODE_INVALID_PARAM
1579
1580     @classmethod
1581     def parser(cls, buf):
1582         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1583         return cls(length)
1584
1585
1586 @chunk_abort.register_cause_code
1587 @chunk_error.register_cause_code
1588 class cause_unrecognized_param(cause_with_value):
1589     """Stream Control Transmission Protocol (SCTP)
1590     sub encoder/decoder class for Unrecognized Parameters (RFC 4960).
1591
1592     This class is used with the following.
1593
1594     - ryu.lib.packet.sctp.chunk_abort
1595     - ryu.lib.packet.sctp.chunk_error
1596
1597     An instance has the following attributes at least.
1598     Most of them are same to the on-wire counterparts but in host byte order.
1599     __init__ takes the corresponding args in this order.
1600
1601     .. tabularcolumns:: |l|L|
1602
1603     ============== =====================================================
1604     Attribute      Description
1605     ============== =====================================================
1606     value          Unrecognized Parameter.
1607     length         length of this cause containing this header.
1608                    (0 means automatically-calculate when encoding)
1609     ============== =====================================================
1610     """
1611
1612     @classmethod
1613     def cause_code(cls):
1614         return CCODE_UNRECOGNIZED_PARAM
1615
1616
1617 @chunk_abort.register_cause_code
1618 @chunk_error.register_cause_code
1619 class cause_no_userdata(cause_with_value):
1620     """Stream Control Transmission Protocol (SCTP)
1621     sub encoder/decoder class for No User Data (RFC 4960).
1622
1623     This class is used with the following.
1624
1625     - ryu.lib.packet.sctp.chunk_abort
1626     - ryu.lib.packet.sctp.chunk_error
1627
1628     An instance has the following attributes at least.
1629     Most of them are same to the on-wire counterparts but in host byte order.
1630     __init__ takes the corresponding args in this order.
1631
1632     .. tabularcolumns:: |l|L|
1633
1634     ============== =====================================================
1635     Attribute      Description
1636     ============== =====================================================
1637     value          the TSN of the DATA chunk received with no user data
1638                    field.
1639     length         length of this cause containing this header.
1640                    (0 means automatically-calculate when encoding)
1641     ============== =====================================================
1642     """
1643
1644     @classmethod
1645     def cause_code(cls):
1646         return CCODE_NO_USERDATA
1647
1648
1649 @chunk_abort.register_cause_code
1650 @chunk_error.register_cause_code
1651 class cause_cookie_while_shutdown(cause):
1652     """Stream Control Transmission Protocol (SCTP)
1653     sub encoder/decoder class for Cookie Received While Shutting Down
1654     (RFC 4960).
1655
1656     This class is used with the following.
1657
1658     - ryu.lib.packet.sctp.chunk_abort
1659     - ryu.lib.packet.sctp.chunk_error
1660
1661     An instance has the following attributes at least.
1662     Most of them are same to the on-wire counterparts but in host byte order.
1663     __init__ takes the corresponding args in this order.
1664
1665     .. tabularcolumns:: |l|L|
1666
1667     ============== =====================================================
1668     Attribute      Description
1669     ============== =====================================================
1670     length         length of this cause containing this header.
1671                    (0 means automatically-calculate when encoding)
1672     ============== =====================================================
1673     """
1674
1675     @classmethod
1676     def cause_code(cls):
1677         return CCODE_COOKIE_WHILE_SHUTDOWN
1678
1679     @classmethod
1680     def parser(cls, buf):
1681         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1682         return cls(length)
1683
1684
1685 @chunk_abort.register_cause_code
1686 @chunk_error.register_cause_code
1687 class cause_restart_with_new_addr(cause_with_value):
1688     """Stream Control Transmission Protocol (SCTP)
1689     sub encoder/decoder class for Restart of an Association with New
1690     Addresses (RFC 4960).
1691
1692     This class is used with the following.
1693
1694     - ryu.lib.packet.sctp.chunk_abort
1695     - ryu.lib.packet.sctp.chunk_error
1696
1697     An instance has the following attributes at least.
1698     Most of them are same to the on-wire counterparts but in host byte order.
1699     __init__ takes the corresponding args in this order.
1700
1701     .. tabularcolumns:: |l|L|
1702
1703     ============== =====================================================
1704     Attribute      Description
1705     ============== =====================================================
1706     value          New Address TLVs.
1707     length         length of this cause containing this header.
1708                    (0 means automatically-calculate when encoding)
1709     ============== =====================================================
1710     """
1711
1712     _class_prefixes = ['param_']
1713     _RECOGNIZED_PARAMS = {}
1714
1715     @staticmethod
1716     def register_param_type(*args):
1717         def _register_param_type(cls):
1718             cause_restart_with_new_addr._RECOGNIZED_PARAMS[
1719                 cls.param_type()] = cls
1720             return cls
1721         return _register_param_type(args[0])
1722
1723     @classmethod
1724     def cause_code(cls):
1725         return CCODE_RESTART_WITH_NEW_ADDR
1726
1727     def __init__(self, value=None, length=0):
1728         if not isinstance(value, list):
1729             value = [value]
1730         super(cause_restart_with_new_addr, self).__init__(value, length)
1731
1732     @classmethod
1733     def parser(cls, buf):
1734         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1735         value = []
1736         offset = cls._MIN_LEN
1737         while offset < length:
1738             (ptype, ) = struct.unpack_from('!H', buf, offset)
1739             cls_ = cls._RECOGNIZED_PARAMS.get(ptype)
1740             if not cls_:
1741                 break
1742             ins = cls_.parser(buf[offset:])
1743             value.append(ins)
1744             offset += len(ins)
1745         return cls(value, length)
1746
1747     def serialize(self):
1748         buf = bytearray(struct.pack(
1749             self._PACK_STR, self.cause_code(), self.length))
1750         for one in self.value:
1751             buf.extend(one.serialize())
1752         if 0 == self.length:
1753             self.length = len(buf)
1754             struct.pack_into('!H', buf, 2, self.length)
1755         mod = len(buf) % 4
1756         if mod:
1757             buf.extend(bytearray(4 - mod))
1758         return six.binary_type(buf)
1759
1760
1761 @chunk_abort.register_cause_code
1762 @chunk_error.register_cause_code
1763 class cause_user_initiated_abort(cause_with_value):
1764     """Stream Control Transmission Protocol (SCTP)
1765     sub encoder/decoder class for User-Initiated Abort (RFC 4960).
1766
1767     This class is used with the following.
1768
1769     - ryu.lib.packet.sctp.chunk_abort
1770     - ryu.lib.packet.sctp.chunk_error
1771
1772     An instance has the following attributes at least.
1773     Most of them are same to the on-wire counterparts but in host byte order.
1774     __init__ takes the corresponding args in this order.
1775
1776     .. tabularcolumns:: |l|L|
1777
1778     ============== =====================================================
1779     Attribute      Description
1780     ============== =====================================================
1781     value          Upper Layer Abort Reason.
1782     length         length of this cause containing this header.
1783                    (0 means automatically-calculate when encoding)
1784     ============== =====================================================
1785     """
1786
1787     @classmethod
1788     def cause_code(cls):
1789         return CCODE_USER_INITIATED_ABORT
1790
1791
1792 @chunk_abort.register_cause_code
1793 @chunk_error.register_cause_code
1794 class cause_protocol_violation(cause_with_value):
1795     """Stream Control Transmission Protocol (SCTP)
1796     sub encoder/decoder class for Protocol Violation (RFC 4960).
1797
1798     This class is used with the following.
1799
1800     - ryu.lib.packet.sctp.chunk_abort
1801     - ryu.lib.packet.sctp.chunk_error
1802
1803     An instance has the following attributes at least.
1804     Most of them are same to the on-wire counterparts but in host byte order.
1805     __init__ takes the corresponding args in this order.
1806
1807     .. tabularcolumns:: |l|L|
1808
1809     ============== =====================================================
1810     Attribute      Description
1811     ============== =====================================================
1812     value          Additional Information.
1813     length         length of this cause containing this header.
1814                    (0 means automatically-calculate when encoding)
1815     ============== =====================================================
1816     """
1817
1818     @classmethod
1819     def cause_code(cls):
1820         return CCODE_PROTOCOL_VIOLATION
1821
1822
1823 # =======================================================================
1824 #
1825 # Chunk Parameter Types
1826 #
1827 # =======================================================================
1828 @six.add_metaclass(abc.ABCMeta)
1829 class param(stringify.StringifyMixin):
1830     _PACK_STR = '!HH'
1831     _MIN_LEN = struct.calcsize(_PACK_STR)
1832
1833     @classmethod
1834     @abc.abstractmethod
1835     def param_type(cls):
1836         pass
1837
1838     def __init__(self, value=None, length=0):
1839         self.length = length
1840         self.value = value
1841
1842     @classmethod
1843     def parser(cls, buf):
1844         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
1845         value = None
1846         if (cls._MIN_LEN < length):
1847             fmt = '%ds' % (length - cls._MIN_LEN)
1848             (value, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
1849         return cls(value, length)
1850
1851     def serialize(self):
1852         buf = bytearray(struct.pack(
1853             self._PACK_STR, self.param_type(), self.length))
1854         if self.value:
1855             buf.extend(self.value)
1856         if 0 == self.length:
1857             self.length = len(buf)
1858             struct.pack_into('!H', buf, 2, self.length)
1859         mod = len(buf) % 4
1860         if mod:
1861             buf.extend(bytearray(4 - mod))
1862         return six.binary_type(buf)
1863
1864     def __len__(self):
1865         length = self.length
1866         mod = length % 4
1867         if mod:
1868             length += 4 - mod
1869         return length
1870
1871
1872 @chunk_heartbeat.register_param_type
1873 @chunk_heartbeat_ack.register_param_type
1874 class param_heartbeat(param):
1875     """Stream Control Transmission Protocol (SCTP)
1876     sub encoder/decoder class for Heartbeat Info Parameter (RFC 4960).
1877
1878     This class is used with the following.
1879
1880     - ryu.lib.packet.sctp.chunk_heartbeat
1881     - ryu.lib.packet.sctp.chunk_heartbeat_ack
1882
1883     An instance has the following attributes at least.
1884     Most of them are same to the on-wire counterparts but in host byte order.
1885     __init__ takes the corresponding args in this order.
1886
1887     .. tabularcolumns:: |l|L|
1888
1889     ============== =====================================================
1890     Attribute      Description
1891     ============== =====================================================
1892     value          the sender-specific heartbeat information.
1893     length         length of this param containing this header.
1894                    (0 means automatically-calculate when encoding)
1895     ============== =====================================================
1896     """
1897
1898     @classmethod
1899     def param_type(cls):
1900         return PTYPE_HEARTBEAT
1901
1902
1903 @chunk_init_ack.register_param_type
1904 class param_state_cookie(param):
1905     """Stream Control Transmission Protocol (SCTP)
1906     sub encoder/decoder class for State Cookie Parameter (RFC 4960).
1907
1908     This class is used with the following.
1909
1910     - ryu.lib.packet.sctp.chunk_init_ack
1911
1912     An instance has the following attributes at least.
1913     Most of them are same to the on-wire counterparts but in host byte order.
1914     __init__ takes the corresponding args in this order.
1915
1916     .. tabularcolumns:: |l|L|
1917
1918     ============== =====================================================
1919     Attribute      Description
1920     ============== =====================================================
1921     value          the state cookie. see Section 5.1.3 in RFC 4960.
1922     length         length of this param containing this header.
1923                    (0 means automatically-calculate when encoding)
1924     ============== =====================================================
1925     """
1926
1927     @classmethod
1928     def param_type(cls):
1929         return PTYPE_STATE_COOKIE
1930
1931
1932 @chunk_init_ack.register_param_type
1933 class param_unrecognized_param(param):
1934     """Stream Control Transmission Protocol (SCTP)
1935     sub encoder/decoder class for Unrecognized Parameter (RFC 4960).
1936
1937     This class is used with the following.
1938
1939     - ryu.lib.packet.sctp.chunk_init_ack
1940
1941     An instance has the following attributes at least.
1942     Most of them are same to the on-wire counterparts but in host byte order.
1943     __init__ takes the corresponding args in this order.
1944
1945     .. tabularcolumns:: |l|L|
1946
1947     ============== =====================================================
1948     Attribute      Description
1949     ============== =====================================================
1950     value          the unrecognized parameter in the INIT chunk.
1951     length         length of this param containing this header.
1952                    (0 means automatically-calculate when encoding)
1953     ============== =====================================================
1954     """
1955
1956     @classmethod
1957     def param_type(cls):
1958         return PTYPE_UNRECOGNIZED_PARAM
1959
1960
1961 @chunk_init.register_param_type
1962 class param_cookie_preserve(param):
1963     """Stream Control Transmission Protocol (SCTP)
1964     sub encoder/decoder class for Cookie Preservative Parameter (RFC 4960).
1965
1966     This class is used with the following.
1967
1968     - ryu.lib.packet.sctp.chunk_init
1969
1970     An instance has the following attributes at least.
1971     Most of them are same to the on-wire counterparts but in host byte order.
1972     __init__ takes the corresponding args in this order.
1973
1974     .. tabularcolumns:: |l|L|
1975
1976     ============== =====================================================
1977     Attribute      Description
1978     ============== =====================================================
1979     value          Suggested Cookie Life-Span Increment (msec).
1980     length         length of this param containing this header.
1981                    (0 means automatically-calculate when encoding)
1982     ============== =====================================================
1983     """
1984
1985     _PACK_STR = '!HHI'
1986     _MIN_LEN = struct.calcsize(_PACK_STR)
1987
1988     @classmethod
1989     def param_type(cls):
1990         return PTYPE_COOKIE_PRESERVE
1991
1992     def __init__(self, value=0, length=0):
1993         super(param_cookie_preserve, self).__init__(value, length)
1994
1995     @classmethod
1996     def parser(cls, buf):
1997         (_, length, value) = struct.unpack_from(cls._PACK_STR, buf)
1998         return cls(value, length)
1999
2000     def serialize(self):
2001         if 0 == self.length:
2002             self.length = self._MIN_LEN
2003         buf = struct.pack(
2004             self._PACK_STR, self.param_type(), self.length, self.value)
2005         return buf
2006
2007
2008 @chunk_init.register_param_type
2009 @chunk_init_ack.register_param_type
2010 class param_ecn(param):
2011     """Stream Control Transmission Protocol (SCTP)
2012     sub encoder/decoder class for ECN Parameter (RFC 4960 Appendix A.).
2013
2014     This class is used with the following.
2015
2016     - ryu.lib.packet.sctp.chunk_init
2017     - ryu.lib.packet.sctp.chunk_init_ack
2018
2019     An instance has the following attributes at least.
2020     Most of them are same to the on-wire counterparts but in host byte order.
2021     __init__ takes the corresponding args in this order.
2022
2023     .. tabularcolumns:: |l|L|
2024
2025     ============== =====================================================
2026     Attribute      Description
2027     ============== =====================================================
2028     value          set to None.
2029     length         length of this param containing this header.
2030                    (0 means automatically-calculate when encoding)
2031     ============== =====================================================
2032     """
2033
2034     @classmethod
2035     def param_type(cls):
2036         return PTYPE_ECN
2037
2038     def __init__(self, value=None, length=0):
2039         super(param_ecn, self).__init__(value, length)
2040         assert 4 == length or 0 == length
2041         assert None is value
2042
2043
2044 @chunk_init.register_param_type
2045 @chunk_init_ack.register_param_type
2046 @cause_unresolvable_addr.register_param_type
2047 @cause_restart_with_new_addr.register_param_type
2048 class param_host_addr(param):
2049     """Stream Control Transmission Protocol (SCTP)
2050     sub encoder/decoder class for Host Name Address Parameter (RFC 4960).
2051
2052     This class is used with the following.
2053
2054     - ryu.lib.packet.sctp.chunk_init
2055     - ryu.lib.packet.sctp.chunk_init_ack
2056
2057     An instance has the following attributes at least.
2058     Most of them are same to the on-wire counterparts but in host byte order.
2059     __init__ takes the corresponding args in this order.
2060
2061     .. tabularcolumns:: |l|L|
2062
2063     ============== =====================================================
2064     Attribute      Description
2065     ============== =====================================================
2066     value          a host name that ends with null terminator.
2067     length         length of this param containing this header.
2068                    (0 means automatically-calculate when encoding)
2069     ============== =====================================================
2070     """
2071
2072     @classmethod
2073     def param_type(cls):
2074         return PTYPE_HOST_ADDR
2075
2076
2077 @chunk_init.register_param_type
2078 class param_supported_addr(param):
2079     """Stream Control Transmission Protocol (SCTP)
2080     sub encoder/decoder class for Supported Address Types Parameter (RFC 4960).
2081
2082     This class is used with the following.
2083
2084     - ryu.lib.packet.sctp.chunk_init
2085
2086     An instance has the following attributes at least.
2087     Most of them are same to the on-wire counterparts but in host byte order.
2088     __init__ takes the corresponding args in this order.
2089
2090     .. tabularcolumns:: |l|L|
2091
2092     ============== =====================================================
2093     Attribute      Description
2094     ============== =====================================================
2095     value          a list of parameter types. odd cases pad with 0x0000.
2096     length         length of this param containing this header.
2097                    (0 means automatically-calculate when encoding)
2098     ============== =====================================================
2099     """
2100
2101     _VALUE_STR = '!H'
2102     _VALUE_LEN = struct.calcsize(_VALUE_STR)
2103
2104     @classmethod
2105     def param_type(cls):
2106         return PTYPE_SUPPORTED_ADDR
2107
2108     def __init__(self, value=None, length=0):
2109         if not isinstance(value, list):
2110             value = [value]
2111         for one in value:
2112             assert isinstance(one, int)
2113         super(param_supported_addr, self).__init__(value, length)
2114
2115     @classmethod
2116     def parser(cls, buf):
2117         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
2118         value = []
2119         offset = cls._MIN_LEN
2120         while offset < length:
2121             (one, ) = struct.unpack_from(cls._VALUE_STR, buf, offset)
2122             value.append(one)
2123             offset += cls._VALUE_LEN
2124         return cls(value, length)
2125
2126     def serialize(self):
2127         buf = bytearray(struct.pack(
2128             self._PACK_STR, self.param_type(), self.length))
2129         for one in self.value:
2130             buf.extend(struct.pack(param_supported_addr._VALUE_STR, one))
2131         if 0 == self.length:
2132             self.length = len(buf)
2133             struct.pack_into('!H', buf, 2, self.length)
2134         mod = len(buf) % 4
2135         if mod:
2136             buf.extend(bytearray(4 - mod))
2137         return six.binary_type(buf)
2138
2139
2140 @chunk_init.register_param_type
2141 @chunk_init_ack.register_param_type
2142 @cause_unresolvable_addr.register_param_type
2143 @cause_restart_with_new_addr.register_param_type
2144 class param_ipv4(param):
2145     """Stream Control Transmission Protocol (SCTP)
2146     sub encoder/decoder class for IPv4 Address Parameter (RFC 4960).
2147
2148     This class is used with the following.
2149
2150     - ryu.lib.packet.sctp.chunk_init
2151     - ryu.lib.packet.sctp.chunk_init_ack
2152
2153     An instance has the following attributes at least.
2154     Most of them are same to the on-wire counterparts but in host byte order.
2155     __init__ takes the corresponding args in this order.
2156
2157     .. tabularcolumns:: |l|L|
2158
2159     ============== =====================================================
2160     Attribute      Description
2161     ============== =====================================================
2162     value          IPv4 address of the sending endpoint.
2163     length         length of this param containing this header.
2164                    (0 means automatically-calculate when encoding)
2165     ============== =====================================================
2166     """
2167
2168     _TYPE = {'ascii': ['value']}
2169
2170     @classmethod
2171     def param_type(cls):
2172         return PTYPE_IPV4
2173
2174     def __init__(self, value='127.0.0.1', length=0):
2175         super(param_ipv4, self).__init__(value, length)
2176
2177     @classmethod
2178     def parser(cls, buf):
2179         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
2180         value = None
2181         if (cls._MIN_LEN < length):
2182             fmt = '%ds' % (length - cls._MIN_LEN)
2183             (value, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
2184         return cls(addrconv.ipv4.bin_to_text(value), length)
2185
2186     def serialize(self):
2187         buf = bytearray(struct.pack(
2188             self._PACK_STR, self.param_type(), self.length))
2189         if self.value:
2190             buf.extend(addrconv.ipv4.text_to_bin(self.value))
2191         if 0 == self.length:
2192             self.length = len(buf)
2193             struct.pack_into('!H', buf, 2, self.length)
2194         return six.binary_type(buf)
2195
2196
2197 @chunk_init.register_param_type
2198 @chunk_init_ack.register_param_type
2199 @cause_unresolvable_addr.register_param_type
2200 @cause_restart_with_new_addr.register_param_type
2201 class param_ipv6(param):
2202     """Stream Control Transmission Protocol (SCTP)
2203     sub encoder/decoder class for IPv6 Address Parameter (RFC 4960).
2204
2205     This class is used with the following.
2206
2207     - ryu.lib.packet.sctp.chunk_init
2208     - ryu.lib.packet.sctp.chunk_init_ack
2209
2210     An instance has the following attributes at least.
2211     Most of them are same to the on-wire counterparts but in host byte order.
2212     __init__ takes the corresponding args in this order.
2213
2214     .. tabularcolumns:: |l|L|
2215
2216     ============== =====================================================
2217     Attribute      Description
2218     ============== =====================================================
2219     value          IPv6 address of the sending endpoint.
2220     length         length of this param containing this header.
2221                    (0 means automatically-calculate when encoding)
2222     ============== =====================================================
2223     """
2224
2225     _TYPE = {'ascii': ['value']}
2226
2227     @classmethod
2228     def param_type(cls):
2229         return PTYPE_IPV6
2230
2231     def __init__(self, value='::1', length=0):
2232         super(param_ipv6, self).__init__(value, length)
2233
2234     @classmethod
2235     def parser(cls, buf):
2236         (_, length) = struct.unpack_from(cls._PACK_STR, buf)
2237         value = None
2238         if (cls._MIN_LEN < length):
2239             fmt = '%ds' % (length - cls._MIN_LEN)
2240             (value, ) = struct.unpack_from(fmt, buf, cls._MIN_LEN)
2241         return cls(addrconv.ipv6.bin_to_text(value), length)
2242
2243     def serialize(self):
2244         buf = bytearray(struct.pack(
2245             self._PACK_STR, self.param_type(), self.length))
2246         if self.value:
2247             buf.extend(addrconv.ipv6.text_to_bin(self.value))
2248         if 0 == self.length:
2249             self.length = len(buf)
2250             struct.pack_into('!H', buf, 2, self.length)
2251         return six.binary_type(buf)