/// <summary> /// Serialises an INIT or INIT ACK chunk to a pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the serialised chunk bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write to.</param> /// <returns>The number of bytes, including padding, written to the buffer.</returns> public override ushort WriteTo(byte[] buffer, int posn) { WriteChunkHeader(buffer, posn); // Write fixed parameters. int startPosn = posn + SCTP_CHUNK_HEADER_LENGTH; NetConvert.ToBuffer(InitiateTag, buffer, startPosn); NetConvert.ToBuffer(ARwnd, buffer, startPosn + 4); NetConvert.ToBuffer(NumberOutboundStreams, buffer, startPosn + 8); NetConvert.ToBuffer(NumberInboundStreams, buffer, startPosn + 10); NetConvert.ToBuffer(InitialTSN, buffer, startPosn + 12); var varParameters = GetVariableParameters(); // Write optional parameters. if (varParameters.Count > 0) { int paramPosn = startPosn + FIXED_PARAMETERS_LENGTH; foreach (var optParam in varParameters) { paramPosn += optParam.WriteTo(buffer, paramPosn); } } return(GetChunkLength(true)); }
public int WriteTo(byte[] buffer, int posn) { NetConvert.ToBuffer((ushort)CauseCode, buffer, posn); NetConvert.ToBuffer(ERROR_CAUSE_LENGTH, buffer, posn + 2); NetConvert.ToBuffer(TSN, buffer, posn + 4); return(ERROR_CAUSE_LENGTH); }
/// <summary> /// Serialises the SACK chunk to a pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the serialised chunk bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write to.</param> /// <returns>The number of bytes, including padding, written to the buffer.</returns> public override ushort WriteTo(byte[] buffer, int posn) { WriteChunkHeader(buffer, posn); ushort startPosn = (ushort)(posn + SCTP_CHUNK_HEADER_LENGTH); NetConvert.ToBuffer(CumulativeTsnAck, buffer, startPosn); NetConvert.ToBuffer(ARwnd, buffer, startPosn + 4); NetConvert.ToBuffer((ushort)GapAckBlocks.Count, buffer, startPosn + 8); NetConvert.ToBuffer((ushort)DuplicateTSN.Count, buffer, startPosn + 10); int reportPosn = startPosn + FIXED_PARAMETERS_LENGTH; foreach (var gapBlock in GapAckBlocks) { NetConvert.ToBuffer(gapBlock.Start, buffer, reportPosn); NetConvert.ToBuffer(gapBlock.End, buffer, reportPosn + 2); reportPosn += GAP_REPORT_LENGTH; } foreach (var dupTSN in DuplicateTSN) { NetConvert.ToBuffer(dupTSN, buffer, reportPosn); reportPosn += DUPLICATE_TSN_LENGTH; } return(GetChunkLength(true)); }
/// <summary> /// Serialises a Data Channel Establishment Protocol (DECP) OPEN message to a /// pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the serialised chunk bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write to.</param> /// <returns>The number of bytes, including padding, written to the buffer.</returns> public ushort WriteTo(byte[] buffer, int posn) { buffer[posn] = MessageType; buffer[posn + 1] = ChannelType; NetConvert.ToBuffer(Priority, buffer, posn + 2); NetConvert.ToBuffer(Reliability, buffer, posn + 4); ushort labelLength = (ushort)(Label != null ? Encoding.UTF8.GetByteCount(Label) : 0); ushort protocolLength = (ushort)(Protocol != null ? Encoding.UTF8.GetByteCount(Protocol) : 0); NetConvert.ToBuffer(labelLength, buffer, posn + 8); NetConvert.ToBuffer(protocolLength, buffer, posn + 10); posn += DCEP_OPEN_FIXED_PARAMETERS_LENGTH; if (labelLength > 0) { Buffer.BlockCopy(Encoding.UTF8.GetBytes(Label), 0, buffer, posn, labelLength); posn += labelLength; } if (protocolLength > 0) { Buffer.BlockCopy(Encoding.UTF8.GetBytes(Protocol), 0, buffer, posn, protocolLength); posn += protocolLength; } return((ushort)posn); }
/// <summary> /// Writes the optional and variable length parameters to a Type-Length-Value (TLV) /// parameter list. /// </summary> /// <returns>A TLV parameter list holding the optional and variable length parameters.</returns> private List <SctpTlvChunkParameter> GetVariableParameters() { List <SctpTlvChunkParameter> varParams = new List <SctpTlvChunkParameter>(); // Add the optional and variable length parameters as Type-Length-Value (TLV) formatted. foreach (var address in Addresses) { ushort addrParamType = (ushort)(address.AddressFamily == AddressFamily.InterNetwork ? SctpInitChunkParameterType.IPv4Address : SctpInitChunkParameterType.IPv6Address); var addrParam = new SctpTlvChunkParameter(addrParamType, address.GetAddressBytes()); varParams.Add(addrParam); } if (CookiePreservative > 0) { varParams.Add( new SctpTlvChunkParameter((ushort)SctpInitChunkParameterType.CookiePreservative, NetConvert.GetBytes(CookiePreservative) )); } if (!string.IsNullOrEmpty(HostnameAddress)) { varParams.Add( new SctpTlvChunkParameter((ushort)SctpInitChunkParameterType.HostNameAddress, Encoding.UTF8.GetBytes(HostnameAddress) )); } if (SupportedAddressTypes.Count > 0) { byte[] paramVal = new byte[SupportedAddressTypes.Count * 2]; int paramValPosn = 0; foreach (var supAddr in SupportedAddressTypes) { NetConvert.ToBuffer((ushort)supAddr, paramVal, paramValPosn); paramValPosn += 2; } varParams.Add( new SctpTlvChunkParameter((ushort)SctpInitChunkParameterType.SupportedAddressTypes, paramVal)); } if (StateCookie != null) { varParams.Add( new SctpTlvChunkParameter((ushort)SctpInitChunkParameterType.StateCookie, StateCookie)); } foreach (var unrecognised in UnrecognizedPeerParameters) { varParams.Add( new SctpTlvChunkParameter((ushort)SctpInitChunkParameterType.UnrecognizedParameter, unrecognised.GetBytes())); } return(varParams); }
public int WriteTo(byte[] buffer, int posn) { var len = GetErrorCauseLength(true); NetConvert.ToBuffer((ushort)CauseCode, buffer, posn); NetConvert.ToBuffer(len, buffer, posn + 2); if (NewAddressTLVs != null) { Buffer.BlockCopy(NewAddressTLVs, 0, buffer, posn + 4, NewAddressTLVs.Length); } return(len); }
public int WriteTo(byte[] buffer, int posn) { var len = GetErrorCauseLength(true); NetConvert.ToBuffer((ushort)CauseCode, buffer, posn); NetConvert.ToBuffer(len, buffer, posn + 2); if (UnrecognizedParameters != null) { Buffer.BlockCopy(UnrecognizedParameters, 0, buffer, posn + 4, UnrecognizedParameters.Length); } return(len); }
/// <summary> /// Verifies whether the checksum for a serialised SCTP packet is valid. /// </summary> /// <param name="buffer">The buffer holding the serialised packet.</param> /// <param name="posn">The start position in the buffer.</param> /// <param name="length">The length of the packet in the buffer.</param> /// <returns>True if the checksum was valid, false if not.</returns> public static bool VerifyChecksum(byte[] buffer, int posn, int length) { uint origChecksum = NetConvert.ParseUInt32(buffer, posn + CHECKSUM_BUFFER_POSITION); NetConvert.ToBuffer(0U, buffer, posn + CHECKSUM_BUFFER_POSITION); uint calcChecksum = CRC32C.Calculate(buffer, posn, length); // Put the original checksum back. NetConvert.ToBuffer(origChecksum, buffer, posn + CHECKSUM_BUFFER_POSITION); return(origChecksum == NetConvert.EndianFlip(calcChecksum)); }
public int WriteTo(byte[] buffer, int posn) { var len = GetErrorCauseLength(true); NetConvert.ToBuffer((ushort)CauseCode, buffer, posn); NetConvert.ToBuffer(len, buffer, posn + 2); if (!string.IsNullOrEmpty(AdditionalInformation)) { var reasonBuffer = Encoding.UTF8.GetBytes(AdditionalInformation); Buffer.BlockCopy(reasonBuffer, 0, buffer, posn + 4, reasonBuffer.Length); } return(len); }
public int WriteTo(byte[] buffer, int posn) { var len = GetErrorCauseLength(true); NetConvert.ToBuffer((ushort)CauseCode, buffer, posn); NetConvert.ToBuffer(len, buffer, posn + 2); if (MissingParameters != null) { int valPosn = posn + 4; foreach (var missing in MissingParameters) { NetConvert.ToBuffer(missing, buffer, valPosn); valPosn += 2; } } return(len); }
/// <summary> /// Serialises a DATA chunk to a pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the serialised chunk bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write to.</param> /// <returns>The number of bytes, including padding, written to the buffer.</returns> public override ushort WriteTo(byte[] buffer, int posn) { WriteChunkHeader(buffer, posn); // Write fixed parameters. int startPosn = posn + SCTP_CHUNK_HEADER_LENGTH; NetConvert.ToBuffer(TSN, buffer, startPosn); NetConvert.ToBuffer(StreamID, buffer, startPosn + 4); NetConvert.ToBuffer(StreamSeqNum, buffer, startPosn + 6); NetConvert.ToBuffer(PPID, buffer, startPosn + 8); int userDataPosn = startPosn + FIXED_PARAMETERS_LENGTH; if (UserData != null) { Buffer.BlockCopy(UserData, 0, buffer, userDataPosn, UserData.Length); } return(GetChunkLength(true)); }
/// <summary> /// Serialises an SCTP packet to a byte array. /// </summary> /// <returns>The byte array containing the serialised SCTP packet.</returns> public byte[] GetBytes() { int chunksLength = Chunks.Sum(x => x.GetChunkLength(true)); byte[] buffer = new byte[SctpHeader.SCTP_HEADER_LENGTH + chunksLength]; Header.WriteToBuffer(buffer, 0); int writePosn = SctpHeader.SCTP_HEADER_LENGTH; foreach (var chunk in Chunks) { writePosn += chunk.WriteTo(buffer, writePosn); } NetConvert.ToBuffer(0U, buffer, CHECKSUM_BUFFER_POSITION); uint checksum = CRC32C.Calculate(buffer, 0, buffer.Length); NetConvert.ToBuffer(NetConvert.EndianFlip(checksum), buffer, CHECKSUM_BUFFER_POSITION); return(buffer); }
/// <summary> /// Serialises the SHUTDOWN chunk to a pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the serialised chunk bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write to.</param> /// <returns>The number of bytes, including padding, written to the buffer.</returns> public override ushort WriteTo(byte[] buffer, int posn) { WriteChunkHeader(buffer, posn); NetConvert.ToBuffer(CumulativeTsnAck.GetValueOrDefault(), buffer, posn + SCTP_CHUNK_HEADER_LENGTH); return(GetChunkLength(true)); }
/// <summary> /// Writes the parameter header to the buffer. All chunk parameters use the same two /// header fields. /// </summary> /// <param name="buffer">The buffer to write the chunk parameter header to.</param> /// <param name="posn">The position in the buffer to write at.</param> protected void WriteParameterHeader(byte[] buffer, int posn) { NetConvert.ToBuffer(ParameterType, buffer, posn); NetConvert.ToBuffer(GetParameterLength(false), buffer, posn + 2); }
/// <summary> /// Serialises the header to a pre-allocated buffer. /// </summary> /// <param name="buffer">The buffer to write the SCTP header bytes to. It /// must have the required space already allocated.</param> /// <param name="posn">The position in the buffer to write the header /// bytes to.</param> public void WriteToBuffer(byte[] buffer, int posn) { NetConvert.ToBuffer(SourcePort, buffer, posn); NetConvert.ToBuffer(DestinationPort, buffer, posn + 2); NetConvert.ToBuffer(VerificationTag, buffer, posn + 4); }
/// <summary> /// Writes the chunk header to the buffer. All chunks use the same three /// header fields. /// </summary> /// <param name="buffer">The buffer to write the chunk header to.</param> /// <param name="posn">The position in the buffer to write at.</param> /// <returns>The padded length of this chunk.</returns> protected void WriteChunkHeader(byte[] buffer, int posn) { buffer[posn] = ChunkType; buffer[posn + 1] = ChunkFlags; NetConvert.ToBuffer(GetChunkLength(false), buffer, posn + 2); }