예제 #1
0
        /// <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));
        }
예제 #2
0
 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);
 }
예제 #3
0
        /// <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));
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        /// <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));
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        /// <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));
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
 /// <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));
 }
예제 #14
0
 /// <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);
 }
예제 #15
0
 /// <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);
 }
예제 #16
0
 /// <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);
 }