public static Frame ReadFromStream(Stream inputStream)
        {
            byte[]   frameBytes = new byte[BW_HEADER_LENGTH];
            string[] authorizationTokens;
            try
            {
                inputStream.Read(frameBytes, 0, BW_HEADER_LENGTH);
                string frameHeader = Encoding.UTF8.GetString(frameBytes);
                authorizationTokens = Regex.Split(frameHeader.Trim(), " ");
            }
            catch (IOException ex)
            {
                throw new IOException("The Header is corrupted.\n", ex);
            }

            if (authorizationTokens.Length != 3)
            {
                throw new CorruptedFrameException("Frame header must have a length of 3.\nCurrent length: " + authorizationTokens.Length);
            }

            Command command = CommandUtils.GetCommand(authorizationTokens[0]);

            int frameLength;

            try
            {
                frameLength = int.Parse(authorizationTokens[1]);
            }
            catch (FormatException ex)
            {
                throw new CorruptedFrameException("The length of the Frame Header is invalid.\n", ex);
            }

            int sequenceNumber;

            try
            {
                sequenceNumber = int.Parse(authorizationTokens[2]);
            }
            catch (FormatException ex)
            {
                throw new CorruptedFrameException("The sequence number is invalid.\n", ex);
            }

            List <VSKeyPair>     vsKeyPairs     = new List <VSKeyPair>();
            List <PayloadObject> payloadObjects = new List <PayloadObject>();
            List <RoutingObject> routingObjects = new List <RoutingObject>();
            string currentLine;

            while (!(currentLine = ReadLine(inputStream)).Equals("end"))
            {
                string[] tokens = Regex.Split(currentLine, " ");
                if (tokens.Length != 3)
                {
                    throw new CorruptedFrameException("The Header does not contain three fields but " + tokens.Length + ".");
                }

                int length;
                try
                {
                    length = int.Parse(tokens[2]);
                    if (length < 0)
                    {
                        throw new CorruptedFrameException("The length of the Header is negative: " + currentLine);
                    }
                }
                catch (FormatException ex)
                {
                    throw new CorruptedFrameException("The length of the Header is corrupted: " + currentLine + "\n", ex);
                }

                switch (tokens[0])
                {
                case "kv":
                    string key    = tokens[1];
                    byte[] vkBody = new byte[length];
                    inputStream.Read(vkBody, 0, length);
                    VSKeyPair vsKeyPair = new VSKeyPair(key, vkBody);
                    vsKeyPairs.Add(vsKeyPair);
                    inputStream.ReadByte();
                    break;

                case "ro":
                    int routingNumber;
                    try
                    {
                        routingNumber = int.Parse(tokens[1]);
                        if (routingNumber < 0 || routingNumber > 255)
                        {
                            throw new CorruptedFrameException("The Routing number must be: 0 < routingNumber > 255: " + currentLine);
                        }
                    }
                    catch (FormatException ex)
                    {
                        throw new CorruptedFrameException("The Routing number must be: 0 < routingNumber > 255: " + currentLine);
                    }
                    byte[] routingBody = new byte[length];
                    inputStream.Read(routingBody, 0, length);
                    RoutingObject routingObject = new RoutingObject(routingNumber, routingBody);
                    routingObjects.Add(routingObject);
                    inputStream.ReadByte();
                    break;

                case "po":
                    PayloadType payloadType;
                    try
                    {
                        payloadType = PayloadUtils.FromString(tokens[1]);
                    }
                    catch (ArgumentException ex)
                    {
                        throw new CorruptedFrameException("The Payload type is invalid: " + currentLine + "\n", ex);
                    }
                    byte[] payloadBody = new byte[length];
                    inputStream.Read(payloadBody, 0, length);
                    PayloadObject payloadObject = new PayloadObject(payloadType, payloadBody);
                    payloadObjects.Add(payloadObject);
                    inputStream.ReadByte();
                    break;

                default:
                    throw new CorruptedFrameException("The Header is invalid: " + currentLine);
                }
            }

            return(new Frame(command, sequenceNumber, vsKeyPairs, payloadObjects, routingObjects));
        }