Skip to content

Commit 07dd616

Browse files
committed
[feat] SCTP parser with support for data, init, init_ack, sack, heartbeat, heartbeat ack, abort, shutdown, shutdown ack, error, cookie echo, cookie ack chunks
1 parent 935edcb commit 07dd616

File tree

2 files changed

+536
-1
lines changed

2 files changed

+536
-1
lines changed

microschc/protocol/sctp.py

+131
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class SCTPFields(str, Enum):
5555
CHUNK_SACK_GAP_ACK_BLOCK_START = f'{SCTP_HEADER_ID}:Selective Ack Gap Ack BLock Start'
5656
CHUNK_SACK_GAP_ACK_BLOCK_END = f'{SCTP_HEADER_ID}:Selective Ack Gap Ack BLock End'
5757
CHUNK_SACK_DUPLICATE_TSN = f'{SCTP_HEADER_ID}:Selective Ack Duplicate TSN'
58+
59+
CHUNK_SHUTDOWN_CUMULATIVE_TSN_ACK = f'{SCTP_HEADER_ID}:Shutdown Cumulative TSN'
60+
61+
CHUNK_COOKIE_ECHO_COOKIE = f'{SCTP_HEADER_ID}:Cookie Echo Cookie'
5862

5963
PARAMETER_TYPE = f'{SCTP_HEADER_ID}:Parameter Type'
6064
PARAMETER_LENGTH = f'{SCTP_HEADER_ID}:Parameter Length'
@@ -204,6 +208,20 @@ def _parse_chunk(self, buffer: Buffer) -> Tuple[List[FieldDescriptor], int]:
204208
chunk_fields: List[FieldDescriptor] = self._parse_chunk_heartbeat(chunk_value)
205209
elif chunk_type_value == SCTPChunkTypes.HEARTBEAT_ACK:
206210
chunk_fields: List[FieldDescriptor] = self._parse_chunk_heartbeat_ack(chunk_value)
211+
elif chunk_type_value == SCTPChunkTypes.ABORT:
212+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_abort(chunk_value)
213+
elif chunk_type_value == SCTPChunkTypes.SHUTDOWN:
214+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_shutdown(chunk_value)
215+
elif chunk_type_value == SCTPChunkTypes.SHUTDOWN_ACK:
216+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_shutdown_ack(chunk_value)
217+
elif chunk_type_value == SCTPChunkTypes.ERROR:
218+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_error(chunk_value)
219+
elif chunk_type_value == SCTPChunkTypes.COOKIE_ECHO:
220+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_cookie_echo(chunk_value)
221+
elif chunk_type_value == SCTPChunkTypes.COOKIE_ACK:
222+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_cookie_ack(chunk_value)
223+
elif chunk_type_value == SCTPChunkTypes.SHUTDOWN_COMPLETE:
224+
chunk_fields: List[FieldDescriptor] = self._parse_chunk_shutdown_complete(chunk_value)
207225
else:
208226
chunk_fields: List[FieldDescriptor] = [FieldDescriptor(id=SCTPFields.CHUNK_VALUE, position=0, value=chunk_value)]
209227
fields.extend(chunk_fields)
@@ -452,6 +470,119 @@ def _parse_chunk_heartbeat_ack(self, buffer: Buffer) -> List[FieldDescriptor]:
452470
parameters = parameters[bits_consumed:]
453471

454472
return fields
473+
474+
def _parse_chunk_abort(self, buffer: Buffer) -> List[FieldDescriptor]:
475+
"""
476+
0 1 2 3
477+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
478+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
479+
| Type = 6 | Reserved |T| Length |
480+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
481+
\ \
482+
/ zero or more Error Causes /
483+
\ \
484+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
485+
"""
486+
fields: List[FieldDescriptor] = []
487+
488+
parameters = buffer
489+
while parameters.length > 0:
490+
parameter_fields, bits_consumed = self._parse_parameter(parameters)
491+
fields.extend(parameter_fields)
492+
parameters = parameters[bits_consumed:]
493+
494+
return fields
495+
496+
def _parse_chunk_shutdown(self, buffer: Buffer) -> List[FieldDescriptor]:
497+
"""
498+
0 1 2 3
499+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
500+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
501+
| Type = 7 | Chunk Flags | Length = 8 |
502+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
503+
| Cumulative TSN Ack |
504+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
505+
"""
506+
fields: List[FieldDescriptor] = []
507+
508+
fields: List[FieldDescriptor] = []
509+
cumulative_tsn_ack: Buffer = buffer[0:32]
510+
fields.append(FieldDescriptor(id=SCTPFields.CHUNK_SHUTDOWN_CUMULATIVE_TSN_ACK, value=cumulative_tsn_ack, position=0))
511+
512+
return fields
513+
514+
def _parse_chunk_shutdown_ack(self, buffer: Buffer) -> List[FieldDescriptor]:
515+
"""
516+
0 1 2 3
517+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
518+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519+
| Type = 8 | Chunk Flags | Length = 4 |
520+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521+
"""
522+
fields: List[FieldDescriptor] = []
523+
return fields
524+
525+
def _parse_chunk_error(self, buffer: Buffer) -> List[FieldDescriptor]:
526+
"""
527+
0 1 2 3
528+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
529+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530+
| Type = 9 | Chunk Flags | Length |
531+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
532+
\ \
533+
/ one or more Error Causes /
534+
\ \
535+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
536+
"""
537+
fields: List[FieldDescriptor] = []
538+
539+
parameters = buffer
540+
while parameters.length > 0:
541+
parameter_fields, bits_consumed = self._parse_parameter(parameters)
542+
fields.extend(parameter_fields)
543+
parameters = parameters[bits_consumed:]
544+
545+
return fields
546+
547+
def _parse_chunk_cookie_echo(self, buffer: Buffer) -> List[FieldDescriptor]:
548+
"""
549+
0 1 2 3
550+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
551+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
552+
| Type = 10 | Chunk Flags | Length |
553+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554+
/ Cookie /
555+
\ \
556+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557+
"""
558+
fields: List[FieldDescriptor] = []
559+
560+
cookie: Buffer = buffer
561+
fields.append(FieldDescriptor(id=SCTPFields.CHUNK_COOKIE_ECHO_COOKIE, value=cookie, position=0))
562+
563+
return fields
564+
565+
def _parse_chunk_cookie_ack(self, buffer: Buffer) -> List[FieldDescriptor]:
566+
"""
567+
0 1 2 3
568+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
569+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570+
| Type = 11 | Chunk Flags | Length = 4 |
571+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572+
"""
573+
fields: List[FieldDescriptor] = []
574+
return fields
575+
576+
def _parse_chunk_shutdown_complete(self, buffer: Buffer) -> List[FieldDescriptor]:
577+
"""
578+
0 1 2 3
579+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
580+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581+
| Type = 14 | Chunk Flags | Length = 4 |
582+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583+
"""
584+
fields: List[FieldDescriptor] = []
585+
return fields
455586

456587
def _parse_parameter(self, buffer: Buffer) -> Tuple[List[FieldDescriptor], int]:
457588
"""

0 commit comments

Comments
 (0)