/// <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); } }
/// <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); } }