/// <summary> /// Decodes a message from a starting point to an end point /// </summary> public static void Decode(byte[] msgData, int level, int startPosition, int endPosition, int levelToIndex, RLPCollection rlpCollection) { if ((msgData == null) || (msgData.Length == 0)) { return; } var currentData = new byte[endPosition - startPosition]; Array.Copy(msgData, startPosition, currentData, 0, currentData.Length); try { var currentPosition = startPosition; while (currentPosition < endPosition) { if (IsListBiggerThan55Bytes(msgData, currentPosition)) { currentPosition = ProcessListBiggerThan55Bytes(msgData, level, levelToIndex, rlpCollection, currentPosition); continue; } if (IsListLessThan55Bytes(msgData, currentPosition)) { currentPosition = ProcessListLessThan55Bytes(msgData, level, levelToIndex, rlpCollection, currentPosition); continue; } if (IsItemBiggerThan55Bytes(msgData, currentPosition)) { currentPosition = ProcessItemBiggerThan55Bytes(msgData, rlpCollection, currentPosition); continue; } if (IsItemLessThan55Bytes(msgData, currentPosition)) { currentPosition = ProcessItemLessThan55Bytes(msgData, rlpCollection, currentPosition); continue; } if (IsNullItem(msgData, currentPosition)) { currentPosition = ProcessNullItem(rlpCollection, currentPosition); continue; } if (IsSigleByteItem(msgData, currentPosition)) { currentPosition = ProcessSingleByteItem(msgData, rlpCollection, currentPosition); } } } catch (Exception ex) { throw new Exception( "Invalid RLP " + currentData.ToHex(), ex); } }
public static IRLPElement DecodeFirstElement(byte[] msgData, int startPos) { var rlpCollection = new RLPCollection(); Decode(msgData, 0, startPos, startPos + 1, 1, rlpCollection); return(rlpCollection[0]); }
/// <summary> /// Parses byte[] message into RLP items /// </summary> /// <param name="msgData">raw RLP data </param> /// <returns> RlpList: outcome of recursive RLP structure </returns> public static RLPCollection Decode(byte[] msgData) { var rlpCollection = new RLPCollection(); Decode(msgData, 0, 0, msgData.Length, 1, rlpCollection); return(rlpCollection); }
private static int ProcessListLessThan55Bytes(byte[] msgData, int level, int levelToIndex, RLPCollection rlpCollection, int currentPosition) { var length = msgData[currentPosition] - OFFSET_SHORT_LIST; var rlpDataLength = length + 1; var rlpData = new byte[length + 1]; Array.Copy(msgData, currentPosition, rlpData, 0, rlpDataLength); var newLevelCollection = new RLPCollection { RLPData = rlpData }; if (length > 0) { Decode(msgData, level + 1, currentPosition + 1, currentPosition + rlpDataLength, levelToIndex, newLevelCollection); } rlpCollection.Add(newLevelCollection); currentPosition += rlpDataLength; return(currentPosition); }
private static int ProcessNullItem(RLPCollection rlpCollection, int currentPosition) { var item = EMPTY_BYTE_ARRAY; var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1; return(currentPosition); }
private static int ProcessSingleByteItem(byte[] msgData, RLPCollection rlpCollection, int currentPosition) { byte[] item = { msgData[currentPosition] }; var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1; return(currentPosition); }
private static int ProcessItemLessThan55Bytes(byte[] msgData, RLPCollection rlpCollection, int currentPosition) { var length = (byte)(msgData[currentPosition] - OFFSET_SHORT_ITEM); var item = new byte[length]; Array.Copy(msgData, currentPosition + 1, item, 0, length); var rlpPrefix = new byte[2]; Array.Copy(msgData, currentPosition, rlpPrefix, 0, 2); var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1 + length; return(currentPosition); }
private static int ProcessListBiggerThan55Bytes(byte[] msgData, int level, int levelToIndex, RLPCollection rlpCollection, int currentPosition) { var lengthOfLength = (byte)(msgData[currentPosition] - OFFSET_LONG_LIST); var length = CalculateLength(lengthOfLength, msgData, currentPosition); var rlpDataLength = lengthOfLength + length + 1; var rlpData = new byte[rlpDataLength]; Array.Copy(msgData, currentPosition, rlpData, 0, rlpDataLength); var newLevelCollection = new RLPCollection { RLPData = rlpData }; Decode(msgData, level + 1, currentPosition + lengthOfLength + 1, currentPosition + rlpDataLength, levelToIndex, newLevelCollection); rlpCollection.Add(newLevelCollection); currentPosition += rlpDataLength; return(currentPosition); }
private static int ProcessItemBiggerThan55Bytes(byte[] msgData, RLPCollection rlpCollection, int currentPosition) { var lengthOfLength = (byte)(msgData[currentPosition] - OFFSET_LONG_ITEM); var length = CalculateLength(lengthOfLength, msgData, currentPosition); // now we can parse an item for data[1]..data[length] var item = new byte[length]; Array.Copy(msgData, currentPosition + lengthOfLength + 1, item, 0, length); var rlpPrefix = new byte[lengthOfLength + 1]; Array.Copy(msgData, currentPosition, rlpPrefix, 0, lengthOfLength + 1); var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += lengthOfLength + length + 1; return(currentPosition); }
public static string Format(IRLPElement element) { var output = new StringBuilder(); if (element == null) { throw new Exception("RLPElement object can't be null"); } if (element is RLPCollection) { RLPCollection rlpCollection = (RLPCollection)element; output.Append("["); foreach (var innerElement in rlpCollection) { Format(innerElement); } output.Append("]"); } else { output.Append(element.RLPData.ToHex() + ", "); } return(output.ToString()); }
/// <summary> /// Decodes a message from a starting point to an end point /// </summary> public static void Decode(byte[] msgData, int level, int startPosition, int endPosition, int levelToIndex, RLPCollection rlpCollection) { if ((msgData == null) || (msgData.Length == 0)) { return; } var currentData = new byte[endPosition - startPosition]; Array.Copy(msgData, startPosition, currentData, 0, currentData.Length); try { var currentPosition = startPosition; while (currentPosition < endPosition) { // It's a list with a payload more than 55 bytes // data[0] - 0xF7 = how many next bytes allocated // for the length of the list if (msgData[currentPosition] > OFFSET_LONG_LIST) { var lengthOfLength = (byte)(msgData[currentPosition] - OFFSET_LONG_LIST); var length = CalculateLength(lengthOfLength, msgData, currentPosition); var rlpDataLength = lengthOfLength + length + 1; var rlpData = new byte[rlpDataLength]; Array.Copy(msgData, currentPosition, rlpData, 0, rlpDataLength); var newLevelCollection = new RLPCollection { RLPData = rlpData }; Decode(msgData, level + 1, currentPosition + lengthOfLength + 1, currentPosition + rlpDataLength, levelToIndex, newLevelCollection); rlpCollection.Add(newLevelCollection); currentPosition += rlpDataLength; continue; } // It's a list with a payload less than 55 bytes if ((msgData[currentPosition] >= OFFSET_SHORT_LIST) && (msgData[currentPosition] <= OFFSET_LONG_LIST)) { var length = msgData[currentPosition] - OFFSET_SHORT_LIST; var rlpDataLength = length + 1; var rlpData = new byte[length + 1]; Array.Copy(msgData, currentPosition, rlpData, 0, rlpDataLength); var newLevelCollection = new RLPCollection { RLPData = rlpData }; if (length > 0) { Decode(msgData, level + 1, currentPosition + 1, currentPosition + rlpDataLength, levelToIndex, newLevelCollection); } rlpCollection.Add(newLevelCollection); currentPosition += rlpDataLength; continue; } // It's an item with a payload more than 55 bytes // data[0] - 0xB7 = how much next bytes allocated for // the length of the string if ((msgData[currentPosition] > OFFSET_LONG_ITEM) && (msgData[currentPosition] < OFFSET_SHORT_LIST)) { var lengthOfLength = (byte)(msgData[currentPosition] - OFFSET_LONG_ITEM); var length = CalculateLength(lengthOfLength, msgData, currentPosition); // now we can parse an item for data[1]..data[length] var item = new byte[length]; Array.Copy(msgData, currentPosition + lengthOfLength + 1, item, 0, length); var rlpPrefix = new byte[lengthOfLength + 1]; Array.Copy(msgData, currentPosition, rlpPrefix, 0, lengthOfLength + 1); var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += lengthOfLength + length + 1; continue; } // It's an item less than 55 bytes long, // data[0] - 0x80 == length of the item if ((msgData[currentPosition] > OFFSET_SHORT_ITEM) && (msgData[currentPosition] <= OFFSET_LONG_ITEM)) { var length = (byte)(msgData[currentPosition] - OFFSET_SHORT_ITEM); var item = new byte[length]; Array.Copy(msgData, currentPosition + 1, item, 0, length); var rlpPrefix = new byte[2]; Array.Copy(msgData, currentPosition, rlpPrefix, 0, 2); var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1 + length; continue; } // null item if (msgData[currentPosition] == OFFSET_SHORT_ITEM) { var item = EMPTY_BYTE_ARRAY; var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1; continue; } // single byte item if (msgData[currentPosition] < OFFSET_SHORT_ITEM) { byte[] item = { msgData[currentPosition] }; var rlpItem = new RLPItem(item); rlpCollection.Add(rlpItem); currentPosition += 1; } } } catch (OutOfMemoryException ex) { throw new Exception( "Invalid RLP (excessive mem allocation while parsing) " + currentData.ToHex(), ex); } catch (Exception ex) { throw new Exception( "Invalid RLP " + currentData.ToHex(), ex); } }