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); }
public virtual void Decode(N2HBinaryReader reader) { var type = FarId == 0 ? AESEngine.AESType.SYMMETRIC : AESEngine.AESType.DEFAULT; RtmfpUtils.Decode(AesDecrypt.Next(type), reader); PrevAesType = type; }
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); }
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; } }
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); } }
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); }
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); }
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); } }
public CookieComputing(OutboundHandshake handshake) { Nonce = new byte[0]; DH = RtmfpUtils.BeginDiffieHellman(ref Nonce, true); }
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; } }