/// <summary> /// Parses an SCTP chunk from a buffer. /// </summary> /// <param name="buffer">The buffer holding the serialised chunk.</param> /// <param name="posn">The position to start parsing at.</param> /// <returns>An SCTP chunk instance.</returns> public static SctpChunk Parse(byte[] buffer, int posn) { if (buffer.Length < posn + SCTP_CHUNK_HEADER_LENGTH) { throw new ApplicationException("Buffer did not contain the minimum of bytes for an SCTP chunk."); } byte chunkType = buffer[posn]; if (Enum.IsDefined(typeof(SctpChunkType), chunkType)) { switch ((SctpChunkType)chunkType) { case SctpChunkType.ABORT: return(SctpAbortChunk.ParseChunk(buffer, posn, true)); case SctpChunkType.DATA: return(SctpDataChunk.ParseChunk(buffer, posn)); case SctpChunkType.ERROR: return(SctpErrorChunk.ParseChunk(buffer, posn, false)); case SctpChunkType.SACK: return(SctpSackChunk.ParseChunk(buffer, posn)); case SctpChunkType.COOKIE_ACK: case SctpChunkType.COOKIE_ECHO: case SctpChunkType.HEARTBEAT: case SctpChunkType.HEARTBEAT_ACK: case SctpChunkType.SHUTDOWN_ACK: case SctpChunkType.SHUTDOWN_COMPLETE: return(ParseBaseChunk(buffer, posn)); case SctpChunkType.INIT: case SctpChunkType.INIT_ACK: return(SctpInitChunk.ParseChunk(buffer, posn)); case SctpChunkType.SHUTDOWN: return(SctpShutdownChunk.ParseChunk(buffer, posn)); default: logger.LogDebug($"TODO: Implement parsing logic for well known chunk type {(SctpChunkType)chunkType}."); return(ParseBaseChunk(buffer, posn)); } } // Shouldn't reach this point. The SCTP packet parsing logic checks if the chunk is // recognised before attempting to parse it. throw new ApplicationException($"SCTP chunk type of {chunkType} was not recognised."); }
/// <summary> /// Sends an SCTP control packet with an abort chunk to terminate /// the association. /// </summary> /// <param name="errorCause">The cause of the abort.</param> public void Abort(ISctpErrorCause errorCause) { if (!_wasAborted) { _wasAborted = true; bool tBit = _remoteVerificationTag != 0; var abortChunk = new SctpAbortChunk(tBit); abortChunk.AddErrorCause(errorCause); SendChunk(abortChunk); OnAborted?.Invoke(errorCause.CauseCode.ToString()); _dataSender.Close(); } }