コード例 #1
0
ファイル: HandShake.cs プロジェクト: zhujingcheng/csharprtmp
        public Session CreateSession(byte[] cookieValue)
        {
            var temp = cookieValue.BytesToString();

            if (!_cookies.ContainsKey(temp))
            {
                Logger.WARN("Creating session for an unknown cookie '{0}' (CPU congestion?)", temp);
                return(null);
            }
            var cookie = _cookies[temp];

            Peer.Id = (byte[])cookie.PeerId.Clone();
            RtmfpUtils.UnpackUrl(cookie.QueryUrl, out Peer.Path, out Peer.Properties);
            FarId        = cookie.FarId;
            Peer.Address = cookie.PeerAddress;
            var session = Handler.CreateSession(Peer, cookie);

            cookie.Id = session.Id;
            cookie.Write();
            if (cookie.Target != null)
            {
                //cookie.Target.InitiatorNonce = cookie.CookieComputing.InitiatorNonce.Clone() as byte[];
                cookie.Target.SharedSecret = cookie.CookieComputing.SharedSecret;
            }
            Writer.Write((byte)0x78);
            Writer.Write(cookie.Length);
            cookie.Read(Writer.BaseStream);
            Flush(0x0b);
            FarId = 0;
            return(session);
        }
コード例 #2
0
ファイル: Session.cs プロジェクト: zhujingcheng/csharprtmp
        public virtual void Decode(N2HBinaryReader reader)
        {
            var type = FarId == 0 ? AESEngine.AESType.SYMMETRIC : AESEngine.AESType.DEFAULT;

            RtmfpUtils.Decode(AesDecrypt.Next(type), reader);
            PrevAesType = type;
        }
コード例 #3
0
        public override void Flush(byte type)
        {
            Writer.BaseStream.Position = 6;
            Writer.Write((byte)0x0b);
            Writer.Write(RtmfpUtils.TimeNow());
            Writer.Write(type);
            Writer.Write((short)(Writer.BaseStream.GetAvaliableByteCounts() - 2));
            var encoder = AesEncrypt.Next(AESEngine.AESType.SYMMETRIC);

            RtmfpUtils.EncodeAndPack(encoder, Writer, 0);
            EnqueueForOutbound(OutputBuffer);
            Writer.Clear(11);
        }
コード例 #4
0
ファイル: Cookie.cs プロジェクト: zhujingcheng/csharprtmp
        public void Run()
        {
            if (DH == null)
            {
                DH = RtmfpUtils.BeginDiffieHellman(ref Nonce);
                return;
            }
            // Compute Diffie-Hellman secret
            SharedSecret = DH.CreateSharedKey(InitiatorKey);
            // Compute Keys
            RtmfpUtils.ComputeAsymetricKeys(SharedSecret, InitiatorNonce, Nonce, out DecryptKey, out EncryptKey);
            var pSession = _handshake?.CreateSession(Value);

            if (pSession != null)
            {
                pSession.Peer.UserState = this;
            }
        }
コード例 #5
0
ファイル: Session.cs プロジェクト: zhujingcheng/csharprtmp
        public void Flush(byte marker, bool echoTime, AESEngine.AESType aesType)
        {
            _lastFlowWriter = null;
            if (IsEnqueueForDelete)
            {
                return;
            }
            var outputBuffer = Writer.BaseStream;

            if (outputBuffer.Length >= Defines.RTMFP_MIN_PACKET_SIZE)
            {
                //Debug.WriteLine(outputBuffer.Length);
                if (RecTimestamp.Elapsed > TimeSpan.FromSeconds(30))
                {
                    echoTime = false;
                }
                var offset = 0;
                if (echoTime)
                {
                    marker += 4;
                }
                else
                {
                    offset = 2;
                }
                var timeStamp = RtmfpUtils.TimeNow();
                //_outputBuffer.Ignore(offset);
                outputBuffer.Position = 6 + offset;
                outputBuffer.WriteByte(marker);
                Writer.Write(timeStamp);
                if (echoTime)
                {
                    Writer.Write((ushort)(TimeSent + RtmfpUtils.Time(RecTimestamp.Elapsed)));
                }
                RtmfpUtils.EncodeAndPack(AesEncrypt.Next(aesType), Writer, FarId, offset);
                EnqueueForOutbound(outputBuffer as MemoryStream, offset);
                Writer.Clear(11);
            }
        }
コード例 #6
0
ファイル: Session.cs プロジェクト: zhujingcheng/csharprtmp
        public virtual void SendStream(Stream stream, int len)
        {
            var marker   = stream.ReadByte() | 0xF0;
            var echoTime = marker == (Target == null ? 0xFE : 0xFD);

            stream.ReadUShort();
            if (echoTime)
            {
                stream.ReadUShort();
            }
            var type = stream.ReadByte();
            var size = stream.ReadUShort();

            switch (type)
            {
            case 0x51:
                var idFlow      = stream.Read7BitLongValue();
                var bufferSize  = stream.Read7BitLongValue();
                var stageReaden = stream.Read7BitLongValue();
                var tail        = "";
                while (stream.GetAvaliableByteCounts() > 0)
                {
                    tail += " " + stream.Read7BitLongValue();
                }
                Debug.WriteLine("from {1}:{0:X} ack {2} on flow {3} {4}", type, Target == null ? "server" : "client", stageReaden, idFlow, tail);
                break;

            case 0x10:
                var flags = stream.ReadByte();
                idFlow = stream.Read7BitLongValue();
                var stage     = stream.Read7BitLongValue();
                var deltaNAck = stream.Read7BitLongValue();
                Debug.WriteLine("from {1}:{0:X} stage {2} deltaNAck {4} on flow {3}", type, Target == null ? "server" : "client", stage, idFlow, deltaNAck);
                if ((flags & FlowWriter.MESSAGE_HEADER) != 0)
                {
                    var signturelen = stream.ReadByte();
                    stream.Position += signturelen;
                    if (stream.ReadByte() > 0)
                    {
                        if (stream.ReadByte() != 0x0A)
                        {
                            Logger.WARN("Unknown fullduplex header part for the flow {0}", idFlow);
                        }
                        else
                        {
                            var assocFlowId = stream.Read7BitLongValue();
                        }
                        var length = stream.ReadByte();
                        while (length > 0 && stream.GetAvaliableByteCounts() > 0)
                        {
                            Logger.WARN("Unknown message part on flow {0}", idFlow);
                            stream.Position += length;
                            length           = stream.ReadByte();
                        }
                        if (length > 0)
                        {
                            Logger.FATAL("Bad header message part, finished before scheduled");
                        }
                    }
                    var stype = stream.ReadByte();//type
                    //var timestamp = stream.ReadUInt();//timestamp
                    switch (stype)
                    {
                    case 0x08:
                    case 0x09:
                        break;

                    case Defines.RM_HEADER_MESSAGETYPE_FLEX:
                        stream.ReadByte();
                        goto case Defines.RM_HEADER_MESSAGETYPE_INVOKE;

                    case Defines.RM_HEADER_MESSAGETYPE_INVOKE:
                        var timestamp = stream.ReadUInt();    //timestamp
                        var amfReader = new AMF0Reader(stream);
                        var str       = amfReader.ReadShortString(true);
                        Logger.Debug("from {1}:{0:X} to {2:X} on flow {3}", type, Target == null ? "server" : "client", str, idFlow);
                        break;

                    default:
                        Logger.Debug("from {1}:{0:X} to {2:X} on flow {3}", type, Target == null ? "server" : "client", stype, idFlow);
                        break;
                    }
                }
                break;

            default:
                Logger.Debug("from {1}:{0:X}", type, Target == null ? "server" : "client");
                break;
            }


            stream.Position        = 0;
            _outputBuffer.Position = 0;
            stream.CopyPartTo(_outputBuffer, len);
            RtmfpUtils.EncodeAndPack(AesEncrypt.Next(PrevAesType), Writer, FarId);
            EnqueueForOutbound(_outputBuffer);
        }
コード例 #7
0
ファイル: Session.cs プロジェクト: zhujingcheng/csharprtmp
        public virtual void PacketHandler(N2HBinaryReader reader)
        {
            if (IsEnqueueForDelete)
            {
                return;
            }
            RecTimestamp.Restart();
            var marker = reader.ReadByte() | 0xF0;

            TimeSent = reader.ReadUInt16();
            if (marker == (Target == null?0xFD:0xFE))
            {
                var time     = RtmfpUtils.TimeNow();
                var timeEcho = reader.ReadUInt16();
                if (timeEcho > time)
                {
                    if (timeEcho - time < 30)
                    {
                        time = 0;
                    }
                    else
                    {
                        time += (ushort)(0xFFFF - timeEcho);
                    }
                    timeEcho = 0;
                }
                Peer.Ping = (ushort)((time - timeEcho) * Defines.RTMFP_TIMESTAMP_SCALE);
            }
            else if (marker != (Target == null ? 0xF9 : 0xFA))
            {
                Logger.WARN("Packet marker unknown:{0}", marker);
                return;
            }
            byte  flags     = 0;
            Flow  flow      = null;
            ulong stage     = 0;
            ulong deltaNAck = 0;
            var   type      = reader.BaseStream.GetAvaliableByteCounts() > 0 ? reader.ReadByte() : (byte)0xFF;

            //Debug.WriteLine("rec:{0:x}",type);
            while (type != 0xFF)
            {
                var  size         = reader.ReadUInt16();
                long nextPos      = reader.BaseStream.Position + size;
                var  oldPublished = (reader.BaseStream as InputStream).Published;
                (reader.BaseStream as InputStream).Published = (uint)nextPos;
                switch (type)
                {
                case 0x0c:
                    Fail("failed on client side");
                    break;

                case 0x4c:
                    _failed = true;
                    EnqueueForDelete();
                    return;

                case 0x01:
                    if (!Peer.Connected)
                    {
                        Fail("Timeout connection client");
                    }
                    else
                    {
                        WriteMessage(0x41, 0);
                    }
                    goto case 0x41;

                case 0x41:
                    Logger.INFO("keepAlive!");
                    _timesKeepalive = 0;
                    break;

                case 0x5e:
                    var idFlow = reader.Read7BitLongValue();
                    if (!FlowWriters.ContainsKey(idFlow))
                    {
                        Logger.WARN("FlowWriter {0} unfound for acknowledgment on session {1}", idFlow, Id);
                    }
                    else
                    {
                        var flowWriter = FlowWriters[idFlow];
                        flowWriter.Fail("flowWriter rejected on session " + Id);
                    }
                    break;

                case 0x18:
                    Fail("ack negative from server");
                    break;

                case 0x51:
                    //Acknowledgment
                    idFlow = reader.Read7BitLongValue();
                    if (FlowWriters.ContainsKey(idFlow))
                    {
                        FlowWriters[idFlow].Acknowledgment(reader);
                    }
                    else
                    {
                        Logger.WARN("FlowWriter {0} unfound for acknowledgment on session {1}", idFlow, Id);
                    }
                    break;

                case 0x10:
                    flags     = reader.ReadByte();
                    idFlow    = reader.Read7BitLongValue();
                    stage     = reader.Read7BitLongValue() - 1;
                    deltaNAck = reader.Read7BitLongValue() - 1;
                    //Debug.WriteLine("10:{0},{1},{2}",idFlow,stage,deltaNAck);
                    if (_failed)
                    {
                        break;
                    }
                    if (Flows.ContainsKey(idFlow))
                    {
                        flow = Flows[idFlow];
                    }
                    if ((flags & FlowWriter.MESSAGE_HEADER) != 0)
                    {
                        var   signature   = reader.ReadString8();
                        ulong assocFlowId = 0;
                        if (reader.ReadByte() > 0)
                        {
                            if (reader.ReadByte() != 0x0A)
                            {
                                Logger.WARN("Unknown fullduplex header part for the flow {0}", idFlow);
                            }
                            else
                            {
                                assocFlowId = reader.Read7BitLongValue();
                            }
                            var length = reader.ReadByte();
                            while (length > 0 && reader.BaseStream.GetAvaliableByteCounts() > 0)
                            {
                                Logger.WARN("Unknown message part on flow {0}", idFlow);
                                reader.BaseStream.Position += length;
                                length = reader.ReadByte();
                            }
                            if (length > 0)
                            {
                                Logger.FATAL("Bad header message part, finished before scheduled");
                            }
                        }
                        if (flow == null)
                        {
                            flow = CreateFlow(idFlow, signature, assocFlowId);
                        }
                    }
                    if (flow == null)
                    {
                    }
                    goto case 0x11;

                case 0x11:
                    ++stage;
                    ++deltaNAck;
                    if (type == 0x11)
                    {
                        flags = reader.ReadByte();
                    }
                    if (flow != null)
                    {
                        flow.FragmentHandler(stage, deltaNAck, reader.BaseStream, flags);
                        if (!string.IsNullOrEmpty(flow.Error))
                        {
                            Fail(flow.Error);
                            flow = null;
                        }
                    }
                    break;

                default:
                    Logger.FATAL("Message type {0} unknown", type);
                    break;
                }

                reader.BaseStream.Position = nextPos;
                (reader.BaseStream as InputStream).Published = oldPublished;
                type = (byte)(reader.BaseStream.GetAvaliableByteCounts() > 0 ? reader.ReadByte() : 0xFF);
                if (flow != null && type != 0x11)
                {
                    flow.Commit();
                    if (flow.Completed)
                    {
                        Flows.Remove(flow.Id);
                        flow.Dispose();
                    }
                    flow = null;
                }
                //else
                //{
                //    Debug.WriteLine("no commit:{0},{1:X}",flow?.Id.ToString() ?? "no flow",type);
                //}
            }
            SFlush(true);
        }
コード例 #8
0
ファイル: HandShake.cs プロジェクト: zhujingcheng/csharprtmp
        private byte PerformHandshake(byte id, N2HBinaryReader reader, long oldPos)
        {
            //Logger.Debug("PerformHandshake{0}", id);
            switch (id)
            {
            case 0x30:
                reader.ReadByte();
                var epdLen = reader.ReadByte() - 1;
                var type   = reader.ReadByte();
                var epd    = reader.ReadBytes(epdLen);
                var tag    = reader.ReadBytes(16);
                Writer.Write((byte)tag.Length);
                Writer.Write(tag);
                if (type == 0x0F)
                {
                    return(Handler.PerformHandshake(tag, Writer, Peer.Address, epd));
                }
                if (type == 0x0a)
                {
                    var tagstr  = tag.BytesToString();
                    var attempt = GetHelloAttempt <HelloAttempt>(tagstr);

                    ushort port;
                    string host;
                    RtmfpUtils.UnpackUrl(epd.BytesToString(), out host, out port, out Peer.Path, out Peer.Properties);

                    var addresses = new List <string>();
                    Peer.OnHandshake(attempt.Count + 1, addresses);
                    if (addresses.Count > 0)
                    {
                        for (var i = 0; i < addresses.Count; i++)
                        {
                            if (addresses[i] == "again")
                            {
                                addresses[i] = host + ":" + port;
                                Writer.WriteAddress(new IPEndPoint(IPAddress.Parse(host), port), i == 0);
                            }
                        }

                        return(0x71);
                    }
                    CreateCookie(Writer, attempt, tag, epd.BytesToString());
                    Writer.Write(_certificat);
                    return(0x70);
                }
                else
                {
                    Logger.FATAL("Unkown handshake first way with '{0}' type", type);
                }
                return(0);

            case 0x38:
                FarId = reader.ReadUInt32();

                if (reader.Read7BitLongValue() != CookieComputing.COOKIE_SIZE)
                {
                    return(0);
                }
                var cookieKey = reader.ReadBytes(CookieComputing.COOKIE_SIZE).BytesToString();
                reader.BaseStream.Position -= CookieComputing.COOKIE_SIZE;
                if (!_cookies.ContainsKey(cookieKey))
                {
                    Logger.WARN("Cookie {0} unknown, maybe already connected (udpBuffer congested?)", cookieKey);
                    return(0);
                }
                var cookie = _cookies[cookieKey];
                cookie.PeerAddress = Peer.Address;
                if (cookie.FarId == 0)
                {
                    cookie.FarId = FarId;
                    reader.BaseStream.Position += CookieComputing.COOKIE_SIZE;
                    var  size     = reader.Read7BitLongValue();
                    var  buffer   = reader.ReadBytes((int)size);
                    uint tempSize = 0;
                    cookie.PeerId = Target.Sha256.ComputeHash(buffer, 0, (int)size);
                    //Native.EVP_Digest(buffer, (uint)size, cookie.PeerId, ref tempSize, Native.EVP_sha256(), IntPtr.Zero);
                    reader.BaseStream.Position -= (long)size;
                    var initiatorKeySize = (int)(reader.Read7BitValue() - 2);
                    reader.BaseStream.Position         += 2;
                    cookie.CookieComputing.InitiatorKey = new byte[initiatorKeySize];
                    reader.BaseStream.Read(cookie.CookieComputing.InitiatorKey, 0, initiatorKeySize);
                    //cookie.CookieComputing.InitiatorKey = reader.ReadBytes((int) initiatorKeySize);
                    cookie.CookieComputing.InitiatorNonce = reader.ReadBytes((int)reader.Read7BitValue());
                    Writer.BaseStream.Position            = oldPos;
                    tempSize = reader.ReadByte();    //0x58
                    if (tempSize != 0x58)
                    {
                        Logger.WARN("not 0x58!!");
                    }
                    cookie.ComputeKeys();
                }
                else if (cookie.Id > 0)
                {
                    cookie.Read(Writer.BaseStream);
                    return(0x78);
                }
                return(0);

            default:
                Logger.FATAL("Unkown handshake packet id {0}", id);
                return(0);
            }
        }
コード例 #9
0
ファイル: Cookie.cs プロジェクト: zhujingcheng/csharprtmp
 public CookieComputing(OutboundHandshake handshake)
 {
     Nonce = new byte[0];
     DH    = RtmfpUtils.BeginDiffieHellman(ref Nonce, true);
 }
コード例 #10
0
        public override void PacketHandler(N2HBinaryReader reader)
        {
            if (Checked)
            {
                lock (Writer)
                {
                    base.PacketHandler(reader);
                }
                return;
            }
            var marker = reader.ReadByte();

            if (marker != 0x0b)
            {
                Logger.FATAL("Marker hand shake wrong:should be 0b and not {0:X}", marker);
                return;
            }
            var time   = reader.ReadUInt16();
            var type   = reader.ReadByte();
            var length = reader.ReadUInt16();

            byte[] tag;
            Logger.Debug("handshake {0:X} len:{1}", type, length);
            Debug.WriteLine("handshake {0:X} len:{1}", type, length);
            switch (type)
            {
            case 0x70:

                tag = reader.ReadBytes(reader.ReadByte());
                var cookieBytes      = reader.ReadBytes(reader.ReadByte());
                var targetCertificat = reader.ReadBytes((int)reader.BaseStream.GetAvaliableByteCounts());
                var nonce            = new byte[0];
                _dh     = RtmfpUtils.BeginDiffieHellman(ref nonce, true);
                Peer.Id = Target.Sha256.ComputeHash(nonce, 0, nonce.Length);
                HandShake38(cookieBytes, nonce);
                _handshake = () => HandShake38(cookieBytes, nonce);
                break;

            case 0x71:
                tag = reader.ReadBytes(reader.ReadByte());
                var flag    = reader.ReadByte();
                var address = new IPEndPoint(new IPAddress(reader.ReadBytes(4)), reader.ReadInt16());

                Target.Address.Port = address.Port;
                Logger.Debug("redirect to {0}", address.ToString());
                Handler.FarProtocol.IOHandler.Socket.Connect(Target.Address);
                _handshake();
                break;

            case 0x78:

                FarId = reader.ReadUInt32();
                var targetNonce = reader.ReadBytes((int)reader.Read7BitLongValue());
                var must58      = reader.ReadByte();
                Debug.WriteLineIf(must58 != 0x58, $"must58!{must58}");
                var key = new byte[RtmfpUtils.KEY_SIZE];
                Buffer.BlockCopy(targetNonce, targetNonce.Length - RtmfpUtils.KEY_SIZE, key, 0, RtmfpUtils.KEY_SIZE);
                var    sharedSecret = _dh.CreateSharedKey(key);
                byte[] decryptKey;
                byte[] encryptKey;
                RtmfpUtils.ComputeAsymetricKeys(sharedSecret, _certificat, targetNonce, out encryptKey, out decryptKey);
                Checked = true;
                _handshakeTimeoutTimer.Stop();
                AesEncrypt  = new AESEngine(encryptKey, AESEngine.Direction.ENCRYPT);
                AesDecrypt  = new AESEngine(decryptKey);
                PrevAesType = AESEngine.AESType.DEFAULT;
                Application = Handler.Application;
                Handler.CreateSession(Peer, null);

                break;

            default:

                break;
            }
        }