public static UDPFrame DecodeUDP(byte[] datagramBytes) { if (datagramBytes.Length < UDPHeaderLength) { throw new ArgumentException(nameof(UDPHeaderLength)); } ushort sourcePort = ByteFns.MakeUshort(datagramBytes[0], datagramBytes[1]); ushort destPort = ByteFns.MakeUshort(datagramBytes[2], datagramBytes[3]); ushort headerAndDataLength = ByteFns.MakeUshort(datagramBytes[4], datagramBytes[5]); ushort checksum = ByteFns.MakeUshort(datagramBytes[6], datagramBytes[7]); var dataBuffer = new byte[datagramBytes.Length - UDPHeaderLength]; Array.Copy(datagramBytes, UDPHeaderLength, dataBuffer, 0, datagramBytes.Length - UDPHeaderLength); return(new UDPFrame { Header = new UDPHeader() { SourcePort = sourcePort, DestinationPort = destPort, HeaderAndDataLength = headerAndDataLength, Checksum = checksum }, Data = dataBuffer }); }
/// <remarks> /// Big endian. Pads last ushort with a zero byte (least significant) if necessary /// </remarks> public static IEnumerable <ushort> DataBytesToShorts(byte[] data) { var oddByteAmount = data.Length % 2 == 1; var neatLimit = oddByteAmount ? data.Length - 1 : data.Length; for (var i = 0; i < neatLimit; i += 2) { yield return(ByteFns.MakeUshort(data[i], data[i + 1])); } if (oddByteAmount) { yield return(ByteFns.MakeUshort(data[data.Length - 1], 0)); } yield break; }
public static IEnumerable <IPv4Frame> IterateFrames(Stream bytes) { byte[] headerBuffer = new byte[HeaderMinSizeBytes]; while (bytes.CanRead) { int bytesRead = bytes.Read(headerBuffer, 0, HeaderMinSizeBytes); if (bytesRead != HeaderMinSizeBytes) { yield break; } int internetHeaderLengthBytes = (int)(headerBuffer[0] & 0xf) * 4; if (internetHeaderLengthBytes != HeaderMinSizeBytes) { throw new NotImplementedException("Header size other than 20 bytes not supported yet"); } // Calculate header validity uint sum = 0; for (int ushortOffset = 0; ushortOffset < 20; ushortOffset += 2) { sum += ByteFns.MakeUshort(headerBuffer[ushortOffset], headerBuffer[ushortOffset + 1]); } ushort onesComplementSum = ChecksumFns.AddCarryGetUshort(sum); int version = (int)((headerBuffer[0] & 0xf0) >> 4); int totalLength = (int)((headerBuffer[2] << 16) | headerBuffer[3]); int protocol = (int)headerBuffer[9]; byte[] sourceAddressBytes = new byte[4]; Array.Copy(headerBuffer, 12, sourceAddressBytes, 0, 4); byte[] destAddressBytes = new byte[4]; Array.Copy(headerBuffer, 16, destAddressBytes, 0, 4); int optionalBytesToSkip = internetHeaderLengthBytes - HeaderMinSizeBytes; bytes.Position = bytes.Position + optionalBytesToSkip; int dataLength = totalLength - internetHeaderLengthBytes; byte[] data = new byte[dataLength]; int dataBytesRead = bytes.Read(data, 0, dataLength); if (dataBytesRead != dataLength) { throw new InvalidOperationException($"Could not read {dataLength} data bytes, got only {dataBytesRead}"); } yield return(new IPv4Frame() { Header = new IPv4Header() { InternetHeaderLength = internetHeaderLengthBytes, TotalLength = totalLength, SourceAddress = new IPAddress(sourceAddressBytes), DestinationAddress = new IPAddress(destAddressBytes), DatagramProtocol = protocol, ChecksumOK = ((ushort)(onesComplementSum ^ 0xffff) == 0), OnesComplementSum = onesComplementSum }, Data = data }); } }