private DhtRpcPacket Query(DhtRpcPacket packet, NodeContact contact) { Transaction transaction = new Transaction(contact.NodeID, contact.NodeEP); try { lock (_transactions) { _transactions.Add(packet.TransactionID, transaction); } lock (transaction) { lock (_sendBufferStream) { _sendBufferStream.Position = 0; packet.WriteTo(_sendBufferStream); if (_proxyEnabled) { _manager.SendDhtPacket(contact.NodeEP, _sendBufferStream.Buffer, 0, (int)_sendBufferStream.Position); } else { _udpClient.SendTo(_sendBufferStream.Buffer, 0, (int)_sendBufferStream.Position, SocketFlags.None, contact.NodeEP); } } if (!Monitor.Wait(transaction, QUERY_TIMEOUT)) { contact.IncrementRpcFailCount(); return(null); } //auto add contact or update last seen time if (contact.NodeID == null) { contact = transaction.ResponsePacket.SourceNode; } KBucket closestBucket = _routingTable.FindClosestBucket(contact.NodeID); NodeContact bucketContact = closestBucket.FindContactInCurrentBucket(contact.NodeID); if (bucketContact == null) { closestBucket.AddContactInCurrentBucket(contact); } else { bucketContact.UpdateLastSeenTime(); } return(transaction.ResponsePacket); } } finally { lock (_transactions) { _transactions.Remove(packet.TransactionID); } } }