public void Acknowledgment(N2HBinaryReader reader) { var bufferSize = reader.Read7BitLongValue(); if (bufferSize == 0) { Fail("Negative acknowledgment"); return; } ulong stageAckPrec = _stageAck; var stageReaden = reader.Read7BitLongValue(); Debug.WriteLine("ack:id:{0},stage:{1},accId:{2}",Id, stageReaden,FlowId); var stage = _stageAck + 1; if (stageReaden > _stage) { Logger.FATAL( "Acknowledgment received {0} superior than the current sending stage {1} on flowWriter {2}", stageReaden, _stage, Id); _stageAck = _stage; } else if (stageReaden <= _stageAck) { if (reader.BaseStream.GetAvaliableByteCounts() == 0) Logger.Debug("Acknowledgment {0} obsolete on flowWriter {1}", stageReaden, Id); } else { _stageAck = stageReaden; } var maxStageRecv = stageReaden; var pos = reader.BaseStream.Position; while (reader.BaseStream.GetAvaliableByteCounts() > 0) { maxStageRecv += reader.Read7BitLongValue() + reader.Read7BitLongValue() + 2; } if (pos != reader.BaseStream.Position) { reader.BaseStream.Position = pos; } ulong lostCount = 0; ulong lostStage = 0; bool repeated = false; bool header = true; bool stop = false; var messageNode = _messagesSent.First; while (messageNode!=null) { var message = messageNode.Value; //if (stop) break; // if (message.Fragments.Count == 0) continue; //var fragmentsLen = message.Fragments.Count; for (var itFrag = 0; itFrag < message.Fragments.Count;) { if (_stageAck >= message.Fragments[itFrag].Stage) { stage++; _ackCount++; message.Fragments.RemoveAt(itFrag); continue; } while (!stop) { if (lostCount == 0) { if (reader.BaseStream.GetAvaliableByteCounts() > 0) { lostCount = reader.Read7BitLongValue() + 1; lostStage = stageReaden + 1; stageReaden = lostStage + lostCount + reader.Read7BitLongValue(); } else { stop = true; break; } } if (lostStage > _stage) { Logger.FATAL("Lost information received {0} have not been yet sent on flowWriter {1}", lostStage, Id); stop = true; } else if (lostStage <= _stageAck) { --lostCount; ++lostStage; continue; } break; } if (stop) break; if (lostStage != stage) { if (repeated) { ++stage; ++itFrag; header = true; } else { _stageAck = stage; } continue; } if (!message.Repeatable) { if (repeated) { itFrag++; stage++; header = true; } else { Logger.INFO("FlowWriter {0} : message {1} lost", Id, stage); --_ackCount; ++_lostCount; _stageAck = stage; } --lostCount; ++lostStage; continue; } repeated = true; if (message.Fragments[itFrag].Stage >= maxStageRecv) { ++stage; header = true; --lostCount; ++lostStage; itFrag++; continue; } Logger.Debug("FlowWriter {0} : stage {1} reapeated", Id, stage); uint available; var fragmentOffset = message.Fragments[itFrag].Offset; var content = message.GetReader(fragmentOffset, out available); message.Fragments[itFrag] = new Message.FragmentInfo(fragmentOffset, _stage); var contentSize = available; itFrag++; byte flags = 0; if (fragmentOffset > 0) flags |= MESSAGE_WITH_BEFOREPART; if (itFrag != message.Fragments.Count) { flags |= MESSAGE_WITH_AFTERPART; contentSize = message.Fragments[itFrag].Offset - fragmentOffset; } var size = contentSize + 4; var bandWriter = Band.Writer; if (!header && size > bandWriter.AvaliableBufferCounts) { Band.Flush(); header = true; } if (header) size += HeaderSize(stage); if (size > bandWriter.AvaliableBufferCounts) Band.Flush(); size -= 3; Flush(Band.WriteMessage((byte)(header ? 0x10 : 0x11), (ushort)size), stage, flags, header, content, (ushort)contentSize); available -= contentSize; header = false; --lostCount; ++lostStage; ++stage; } if (message.Fragments.Count == 0) { if (message.Repeatable) --_repeatable; if (_ackCount > 0) { uint available; uint size; var reader1 = message.MemAck(out available, out size); AckMessageHandler(_ackCount, _lostCount, reader1, available, size); _ackCount = _lostCount = 0; } _messagesSent.Remove(messageNode); Debug.WriteLine("sentremove{0} on flowWriter {1}", _stageAck, Id); message.Recycle(); } messageNode = messageNode.Next; } if (lostCount > 0 && reader.BaseStream.GetAvaliableByteCounts() > 0) Logger.FATAL("Some lost information received have not been yet sent on flowWriter {0}", Id); // rest messages repeatable? if (_repeatable == 0) _trigger.Stop(); else if (_stageAck > stageAckPrec || repeated) _trigger.Reset(); }
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 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); 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; } }