public static void RegisterProtocol(RtmpProtocol protocol)
        {
            // valid version numbers range from 3 - 31
            if (protocol.ProtocolVersion < 3 || protocol.ProtocolVersion > 31)
            {
                throw new ArgumentException("Invalid version number", "protocol");
            }

            _protocols[protocol.ProtocolVersion] = protocol;
        }
        private RtmpErrors DoHandshake()
        {
            uint       streamEpoch = 0;
            RtmpErrors retval      = RtmpErrors.Success;

            // Step 1: Read C0
            var c0 = _reader.ReadByte();

            // does the client have a protocol that we have?
            if (!_protocols.ContainsKey(c0))
            {
                retval = RtmpErrors.InvalidVersion;
                goto close;
            }

            _selectedProtocol = _protocols[c0];
            // Step 2: Write S0
            _writer.Write(_selectedProtocol.ProtocolVersion);

            // Step 3: Read C1
            var c1Time = _reader.ReadUInt32();
            var c1Zero = _reader.ReadUInt32();
            var c1Rand = _reader.ReadBytes(1528);

            streamEpoch = c1Time;
            // second 4 bytes must be 0
            if (c1Zero != 0)
            {
                retval = RtmpErrors.HandshakeError;
                goto close;
            }

            // Step 4: Write S1
            var s1Time = 0;
            var s1Rand = new byte[1528];

            new Random().NextBytes(s1Rand);
            _writer.Write(s1Time);
            _writer.Write(0);
            _writer.Write(s1Rand);

            // Step 5: Write S2
            _writer.Write(c1Time);
            _writer.Write(0);
            _writer.Write(c1Rand);

            // Step 6: Read C2
            var c2AckTime = _reader.ReadUInt32();
            var c2time    = _reader.ReadUInt32();
            var c2Rand    = _reader.ReadBytes(1528);

            // Verify the client sent back the correct time
            if (c2AckTime != 0)
            {
                retval = RtmpErrors.HandshakeError;
                goto close;
            }

            // Vertify the client sent back the correct rand data
            for (int i = 0; i < 1528; i++)
            {
                if (s1Rand[i] != c2Rand[i])
                {
                    retval = RtmpErrors.HandshakeError;
                    goto close;
                }
            }

            _epoch = streamEpoch;
            goto ret;

close:
            _reader.Close();
            _writer.Close();
            _baseStream.Close();

ret:
            return(retval);
        }