예제 #1
0
        public static LocalDrpPeerConfiguration  Create(ICryptoLibrary cryptoLibrary, int?numberOfDimensions = null, byte[] ed25519privateKey = null, RegistrationId registrationId = null)
        {
            LocalDrpPeerConfiguration r;

            if (ed25519privateKey != null && registrationId != null)
            {
                r = new LocalDrpPeerConfiguration
                {
                    LocalPeerRegistrationPrivateKey = new RegistrationPrivateKey {
                        ed25519privateKey = ed25519privateKey
                    },
                    LocalPeerRegistrationId = registrationId
                };
            }
            else
            {
                RegistrationId.CreateNew(cryptoLibrary, out var newPrivateKey, out var newRegistrationId);
                r = new LocalDrpPeerConfiguration
                {
                    LocalPeerRegistrationPrivateKey = newPrivateKey,
                    LocalPeerRegistrationId         = newRegistrationId
                };
            }

            if (numberOfDimensions == 2)
            {
                r.MinDesiredNumberOfNeighbors  = 5;
                r.SoftMaxNumberOfNeighbors     = 7;
                r.AbsoluteMaxNumberOfNeighbors = 10;
            }
            return(r);
        }
예제 #2
0
 public static void CreateNew(ICryptoLibrary cryptoLibrary, out RegistrationPrivateKey privateKey, out RegistrationId registrationId)
 {
     privateKey = new RegistrationPrivateKey {
         ed25519privateKey = cryptoLibrary.GeneratePrivateKeyEd25519()
     };
     registrationId = new RegistrationId(cryptoLibrary.GetPublicKeyEd25519(privateKey.ed25519privateKey));
 }
예제 #3
0
        internal void TestDirection(Logger logger, RegistrationId destinationRegId)
        {
            if (this.Configuration.LocalPeerRegistrationId.Equals(destinationRegId) == true)
            {
                return;
            }
            var diff = RegistrationId.GetDifferenceVector(this.Configuration.LocalPeerRegistrationId, destinationRegId, CryptoLibrary, Engine.Configuration.SandboxModeOnly_NumberOfDimensions);

            _ = TestDirection(logger, diff);
        }
예제 #4
0
        public static RegistrationId Decode(BinaryReader reader)
        {
            var flags = reader.ReadByte();

            if ((flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            var r = new RegistrationId(reader.ReadBytes(CryptoLibraries.Ed25519PublicKeySize));

            return(r);
        }
예제 #5
0
        public static double[] GetDifferenceVector(RegistrationId from, RegistrationId to, ICryptoLibrary cryptoLibrary, int numberOfDimensions)
        {
            var fromRegIdVector        = RegistrationIdDistance.GetVectorValues(cryptoLibrary, from, numberOfDimensions);
            var destinationRegIdVector = RegistrationIdDistance.GetVectorValues(cryptoLibrary, to, numberOfDimensions);
            var diff = new double[fromRegIdVector.Length];

            for (int i = 0; i < diff.Length; i++)
            {
                diff[i] = RegistrationIdDistance.GetDifferenceInLoopedRegistrationIdSpace(fromRegIdVector[i], destinationRegIdVector[i]);
            }
            return(diff);
        }
예제 #6
0
        public static double GetMutualP2pConnectionValue(ICryptoLibrary cryptoLibrary, RegistrationId registrationId1, ushort neighborsBusySectorIds1,
                                                         RegistrationId registrationId2, ushort neighborsBusySectorIds2, int numberOfDimensions,
                                                         bool thisConnectionAlreadyExists, bool anotherNeighborToSameSectorExists1, bool anotherNeighborToSameSectorExists2, bool allowConnectionsToSameRegistrationId)
        {
            if (registrationId1.Equals(registrationId2))
            {
                return(allowConnectionsToSameRegistrationId ? SameRegistrationIdConnectionValue : -SameRegistrationIdConnectionValue);
            }

            double r        = 0;
            var    distance = registrationId1.GetDistanceTo(cryptoLibrary, registrationId2, numberOfDimensions).ToDouble();

            r -= distance;

            if (thisConnectionAlreadyExists)
            {
                if (anotherNeighborToSameSectorExists1 == false)
                {
                    r += EmptySectorOccupationValue;
                }
                if (anotherNeighborToSameSectorExists2 == false)
                {
                    r += EmptySectorOccupationValue;
                }
            }
            else
            {
                var vsic                       = new VectorSectorIndexCalculator(numberOfDimensions);
                var vector1to2                 = RegistrationId.GetDifferenceVectorF(registrationId1, registrationId2, cryptoLibrary, numberOfDimensions);
                var vector1to2SectorIndex      = vsic.GetSectorIndex(vector1to2);
                var vector1to2IsInVacantSector = ((neighborsBusySectorIds1 >> vector1to2SectorIndex) & 0x0001) == 0;
                if (vector1to2IsInVacantSector)
                {
                    r += EmptySectorOccupationValue;
                }

                var vector2to1 = new float[numberOfDimensions];
                for (int i = 0; i < numberOfDimensions; i++)
                {
                    vector2to1[i] = -vector1to2[i];
                }
                var vector2to1SectorIndex = vsic.GetSectorIndex(vector2to1);

                var vector2to1IsInVacantSector = ((neighborsBusySectorIds2 >> vector2to1SectorIndex) & 0x0001) == 0;
                if (vector2to1IsInVacantSector)
                {
                    r += EmptySectorOccupationValue;
                }
            }

            return(r);
        }
예제 #7
0
        internal void TestDirection(Logger logger, RegistrationId destinationRegId)
        {
            if (this.Configuration.LocalPeerRegistrationId.Equals(destinationRegId) == true)
            {
                return;
            }
            if (this.Configuration.AbsoluteMaxNumberOfNeighbors == 1)
            {
                return;                                                       // special case: mobile device connected to home device
            }
            var diff = RegistrationId.GetDifferenceVector(this.Configuration.LocalPeerRegistrationId, destinationRegId, CryptoLibrary, Engine.Configuration.SandboxModeOnly_NumberOfDimensions);

            _ = TestDirection(logger, diff);
        }
예제 #8
0
 public static float[] GetDifferenceVectorF(RegistrationId from, RegistrationId to, ICryptoLibrary cryptoLibrary, int numberOfDimensions)
 => GetDifferenceVector(from, to, cryptoLibrary, numberOfDimensions).Select(x => (float)x).ToArray();
예제 #9
0
 public RegistrationIdDistance GetDistanceTo(ICryptoLibrary cryptoLibrary, RegistrationId another, int numberOfDimensions) => new RegistrationIdDistance(cryptoLibrary, this, another, numberOfDimensions);
예제 #10
0
        public static LocalDrpPeerConfiguration  Create(ICryptoLibrary cryptoLibrary, int numberOfDimensions, byte[] ed25519privateKey = null, RegistrationId registrationId = null)
        {
            var privatekey = new RegistrationPrivateKey {
                ed25519privateKey = ed25519privateKey ?? cryptoLibrary.GeneratePrivateKeyEd25519()
            };
            var r = new LocalDrpPeerConfiguration
            {
                LocalPeerRegistrationPrivateKey = privatekey,
                LocalPeerRegistrationId         = new RegistrationId(registrationId?.Ed25519publicKey ?? cryptoLibrary.GetPublicKeyEd25519(privatekey.ed25519privateKey))
            };

            if (numberOfDimensions == 2)
            {
                r.MinDesiredNumberOfNeighbors  = 5;
                r.SoftMaxNumberOfNeighbors     = 7;
                r.AbsoluteMaxNumberOfNeighbors = 10;
            }
            return(r);
        }
예제 #11
0
        public static unsafe double[] GetVectorValues(ICryptoLibrary cryptoLibrary, RegistrationId rid, int numberOfDimensions)
        {
            var r = new double[numberOfDimensions];

            if (rid.CachedEd25519publicKeySha256 == null)
            {
                rid.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rid.Ed25519publicKey);
            }
            var rid_ed25519publicKey_sha256 = rid.CachedEd25519publicKeySha256;

            if (numberOfDimensions == 16)
            {
                fixed(byte *rpk1a = rid_ed25519publicKey_sha256)
                {
                    ushort *rpk1aPtr = (ushort *)rpk1a;
                    int     l        = rid_ed25519publicKey_sha256.Length / 2;

                    for (int i = 0; i < l; i++, rpk1aPtr++)
                    {
                        r[i] = (double)(*rpk1aPtr) / UInt16.MaxValue;
                    }
                }
            }
            else if (numberOfDimensions == 8)
            {
                fixed(byte *rpk1a = rid_ed25519publicKey_sha256)
                {
                    uint *rpk1aPtr = (uint *)rpk1a;
                    int   l        = rid_ed25519publicKey_sha256.Length / 4;

                    for (int i = 0; i < l; i++, rpk1aPtr++)
                    {
                        r[i] = (double)(*rpk1aPtr) / UInt32.MaxValue;
                    }
                }
            }
            else if (numberOfDimensions == 4)
            {
                fixed(byte *rpk1a = rid_ed25519publicKey_sha256)
                {
                    ulong *rpk1aPtr = (ulong *)rpk1a;
                    int    l        = rid_ed25519publicKey_sha256.Length / 8;

                    for (int i = 0; i < l; i++, rpk1aPtr++)
                    {
                        r[i] = (double)(*rpk1aPtr) / ulong.MaxValue;
                    }
                }
            }
            else if (numberOfDimensions == 2)
            {
                GetVectorValues_2(rid_ed25519publicKey_sha256, out var v0, out var v1);
                r[0] = v0;
                r[1] = v1;
            }
            else
            {
                throw new NotImplementedException();
            }

            return(r);
        }
예제 #12
0
        public void BeginSendShortSingleMessage(UserCertificate requesterUserCertificate, RegistrationId responderRegistrationId, UserId responderUserId,
                                                string messageText, TimeSpan?retryOnFailureUntilThisTimeout, Action <Exception> cb)
        {
            Engine.EngineThreadQueue.Enqueue(async() =>
            {
                var sw1 = Stopwatch.StartNew();

                _retry:
                Logger logger = null;
                try
                {
                    var sw2     = Stopwatch.StartNew();
                    var session = await SendInviteAsync(requesterUserCertificate, responderRegistrationId, responderUserId, SessionType.asyncShortSingleMessage, (logger2) =>
                    {
                        logger = logger2;
                        if (Engine.Configuration.SandboxModeOnly_EnableInsecureLogs)
                        {
                            if (logger.WriteToLog_detail_enabled)
                            {
                                logger.WriteToLog_detail($"creating an invite session to send a message '{messageText}'");
                            }
                        }
                    });
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"invite session is ready to set up direct channel and send a message");
                    }
                    try
                    {
                        if (logger.WriteToLog_detail_enabled)
                        {
                            logger.WriteToLog_detail($"remote peer accepted invite session in {(int)sw2.Elapsed.TotalMilliseconds}ms: {session.RemoteSessionDescription}");
                        }

                        await session.SetupAEkeysAsync();

                        await session.SendShortSingleMessageAsync(messageText, requesterUserCertificate);
                    }
                    finally
                    {
                        session.Dispose();
                    }

                    cb?.Invoke(null);
                }
                catch (Exception exc)
                {
                    var tryAgain = retryOnFailureUntilThisTimeout.HasValue && sw1.Elapsed < retryOnFailureUntilThisTimeout.Value;
                    logger?.WriteToLog_mediumPain($"sending INVITE failed (tryAgain={tryAgain}): {exc}");
                    logger?.WriteToLog_mediumPain_EmitListOfPeers($"sending INVITE failed (tryAgain={tryAgain}): {exc}");
                    if (tryAgain)
                    {
                        logger?.WriteToLog_higherLevelDetail($"trying again to send message: sw1={sw1.Elapsed.TotalSeconds}s < retryOnFailureUntilThisTimeout={retryOnFailureUntilThisTimeout.Value.TotalSeconds}s");
                        goto _retry;
                    }
                    cb?.Invoke(exc);
                }
            }, "BeginSendShortSingleMessage6342");
        }
예제 #13
0
        public bool Verify(ICryptoLibrary cryptoLibrary, Action <BinaryWriter> writeSignedFields, RegistrationId publicKey)
        {
            var signedData = new MemoryStream();

            using (var writer = new BinaryWriter(signedData))
                writeSignedFields(writer);
            if (cryptoLibrary.VerifyEd25519(signedData.ToArray(), ed25519signature, publicKey.Ed25519publicKey) == false)
            {
                return(false);
            }
            return(true);
        }
예제 #14
0
        public static RegistrationSignature DecodeAndVerify(BinaryReader reader, ICryptoLibrary cryptoLibrary, Action <BinaryWriter> writeSignedFields, RegistrationId publicKey)
        {
            var r = Decode(reader);

            if (!r.Verify(cryptoLibrary, writeSignedFields, publicKey))
            {
                throw new BadSignatureException("invalid registration signature 135");
            }
            return(r);
        }
예제 #15
0
        /// <summary>
        /// sends INVITE, autenticates users, returns Session to be used to create direct cannel
        /// </summary>
        /// <param name="responderUserId">
        /// comes from local contact book
        /// </param>
        /// <param name="responderRegId">
        /// comes from local contact book
        /// </param>
        /// <param name="loggerCb">may be invoked more than one time (in case of retrying)</param>
        public async Task <InviteSession> SendInviteAsync(UserCertificate requesterUserCertificate, RegistrationId responderRegistrationId, UserId responderUserId,
                                                          SessionType sessionType, Action <Logger> loggerCb = null)
        {
            InviteSession session = null;

            try
            {
                var           sw            = Stopwatch.StartNew();
                RoutedRequest routedRequest = null;
                int           trialsCount   = 0;
                Exception     latestTriedNeighborException = null;


_retry:
                trialsCount++;
                session = new InviteSession(this);
                var req = new InviteRequestPacket
                {
                    NumberOfHopsRemaining   = InviteRequestPacket.MaxNumberOfHopsRemaining,
                    RequesterEcdhePublicKey = new EcdhPublicKey(session.LocalInviteAckEcdhePublicKey),
                    RequesterRegistrationId = this.Configuration.LocalPeerRegistrationId,
                    ResponderRegistrationId = responderRegistrationId,
                    ReqTimestamp32S         = Engine.Timestamp32S,
                };
                var logger = new Logger(Engine, this, req, DrpPeerEngine.VisionChannelModuleName_inv_requesterSide);
                if (!Engine.RecentUniqueInviteRequests.Filter(req.GetUniqueRequestIdFields))
                {
                    if (trialsCount > 50)
                    {
                        throw new NonUniquePacketFieldsException($"could not find unique fields to send INVITE request");
                    }
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"waiting a second to generate ne wunique INVITE request");
                    }
                    await Engine.EngineThreadQueue.WaitAsync(TimeSpan.FromSeconds(1), "inv_wait_1236");

                    goto _retry;
                }


                session.Logger = logger;
                loggerCb?.Invoke(logger);
                Engine.RecentUniquePublicEcdhKeys.AssertIsUnique(req.RequesterEcdhePublicKey.Ecdh25519PublicKey, "req.RequesterEcdhePublicKey");
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"generated unique ECDH key {req.RequesterEcdhePublicKey}");
                }
                req.RequesterRegistrationSignature = RegistrationSignature.Sign(Engine.CryptoLibrary, req.GetSharedSignedFields, this.Configuration.LocalPeerRegistrationPrivateKey);

                this.TestDirection(logger, req.ResponderRegistrationId);
                routedRequest = new RoutedRequest(logger, null, null, null, req, null, routedRequest);

                // find best connected peer to send the request
                var destinationPeer = Engine.RouteInviteRequest(this, routedRequest);
                if (destinationPeer == null)
                {
                    if (latestTriedNeighborException == null)
                    {
                        throw new NoNeighborsToSendInviteException();
                    }
                    else
                    {
                        throw latestTriedNeighborException;
                    }
                }
                InviteAck1Packet ack1;
                try
                {
                    var reqUdpData = req.Encode_SetP2pFields(destinationPeer);
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"sending {req} (ReqTimestamp32S={MiscProcedures.Uint32secondsToDateTime(req.ReqTimestamp32S)}), waiting for NPACK");
                    }

                    var sentRequest = new SentRequest(Engine, logger, destinationPeer.RemoteEndpoint, destinationPeer, reqUdpData, req.ReqP2pSeq16, InviteAck1Packet.GetScanner(logger, req, destinationPeer));
                    var ack1UdpData = await sentRequest.SendRequestAsync("ack1 4146");

                    #region process ACK1
                    // NeighborHMAC and NeighborToken32 are already verified by scanner
                    ack1 = InviteAck1Packet.Decode(ack1UdpData);
                    Engine.RecentUniquePublicEcdhKeys.AssertIsUnique(ack1.ResponderEcdhePublicKey.Ecdh25519PublicKey, $"ack1.ResponderEcdhePublicKey");
                    if (!ack1.ResponderRegistrationSignature.Verify(Engine.CryptoLibrary, w =>
                    {
                        req.GetSharedSignedFields(w);
                        ack1.GetSharedSignedFields(w, true);
                    },
                                                                    responderRegistrationId))
                    {
                        throw new BadSignatureException("invalid REGISTER ACK1 ResponderRegistrationSignature 2349");
                    }
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"verified ACK1");
                    }
                    session.DeriveSharedInviteAckDhSecret(Engine.CryptoLibrary, ack1.ResponderEcdhePublicKey.Ecdh25519PublicKey);

                    // send NPACK to ACK1
                    SendNeighborPeerAckResponseToAck1(ack1, destinationPeer);
                    #endregion
                }
                catch (RequestFailedException exc2)
                {
                    latestTriedNeighborException = exc2;
                    if (trialsCount > 50)
                    {
                        throw;
                    }
                    logger.WriteToLog_higherLevelDetail($"trying again on error {exc2.Message}... alreadyTriedProxyingToDestinationPeers.Count={routedRequest.TriedNeighbors.Count}");
                    routedRequest.TriedNeighbors.Add(destinationPeer);
                    goto _retry;
                }

                // decode and verify SD
                session.RemoteSessionDescription = InviteSessionDescription.Decrypt_Verify(Engine.CryptoLibrary,
                                                                                           ack1.ToResponderSessionDescriptionEncrypted,
                                                                                           req, ack1, false, session,
                                                                                           responderUserId, Engine.DateTimeNowUtc);

                // sign and encode local SD
                session.LocalSessionDescription = new InviteSessionDescription
                {
                    DirectChannelEndPoint = destinationPeer.LocalEndpoint,
                    SessionType           = sessionType,
                    DirectChannelToken32  = session.LocalDirectChannelToken32
                };

                session.LocalSessionDescription.UserCertificate = requesterUserCertificate;

                session.LocalSessionDescription.UserCertificateSignature = UserCertificateSignature.Sign(Engine.CryptoLibrary,
                                                                                                         w =>
                {
                    req.GetSharedSignedFields(w);
                    ack1.GetSharedSignedFields(w, true);
                    session.LocalSessionDescription.WriteSignedFields(w);
                },
                                                                                                         requesterUserCertificate
                                                                                                         );

                #region send ack2
                var ack2 = new InviteAck2Packet
                {
                    RequesterRegistrationId = req.RequesterRegistrationId,
                    ResponderRegistrationId = req.ResponderRegistrationId,
                    ReqTimestamp32S         = req.ReqTimestamp32S,
                    ToRequesterSessionDescriptionEncrypted = session.LocalSessionDescription.Encrypt(Engine.CryptoLibrary, req, ack1, session, true)
                };
                ack2.RequesterRegistrationSignature = RegistrationSignature.Sign(Engine.CryptoLibrary, w =>
                {
                    req.GetSharedSignedFields(w);
                    ack1.GetSharedSignedFields(w, true);
                    ack2.GetSharedSignedFields(w);
                }, this.Configuration.LocalPeerRegistrationPrivateKey);
                var ack2UdpData = ack2.Encode_SetP2pFields(destinationPeer);

                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"sending ACK2, waiting for NPACK");
                }
                await destinationPeer.SendUdpRequestAsync_Retransmit_WaitForNPACK("ack2 234575672", ack2UdpData, ack2.ReqP2pSeq16, ack2.GetSignedFieldsForNeighborHMAC);

                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"received NPACK");
                }
                #endregion

                #region wait for CFM
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"waiting for CFM");
                }
                var cfmUdpData = await Engine.WaitForUdpResponseAsync(new PendingLowLevelUdpRequest("cfm 1235695", destinationPeer.RemoteEndpoint,
                                                                                                    InviteConfirmationPacket.GetScanner(logger, req, destinationPeer),
                                                                                                    Engine.DateTimeNowUtc, Engine.Configuration.CfmTimoutS
                                                                                                    ));

                if (cfmUdpData == null)
                {
                    throw new DrpTimeoutException($"did not get CFM at invite requester from destination peer {destinationPeer} (timeout={Engine.Configuration.CfmTimoutS}s)");
                }

                // NeighborHMAC and NeighborToken32 are already verified by scanner
                var cfm = InviteConfirmationPacket.Decode(cfmUdpData);

                if (!cfm.ResponderRegistrationSignature.Verify(Engine.CryptoLibrary, w =>
                {
                    req.GetSharedSignedFields(w);
                    ack1.GetSharedSignedFields(w, true);
                    ack2.GetSharedSignedFields(w);
                },
                                                               responderRegistrationId))
                {
                    throw new BadSignatureException("invalid REGISTER CFM ResponderRegistrationSignature 6398");
                }

                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"verified CFM");
                }

                // send NPACK to CFM
                SendNeighborPeerAckResponseToCfm(cfm, destinationPeer);
                #endregion

                session.DeriveSharedPingPongHmacKey(req, ack1, ack2, cfm);
                return(session);
            }
            catch
            {
                session?.Dispose();
                throw;
            }
        }
예제 #16
0
        double _distance_sumSqr; // 32 bytes of reg. public key: split into 16 dimensions of 2 bytes //   euclidean distance
        public unsafe RegistrationIdDistance(ICryptoLibrary cryptoLibrary, RegistrationId rpk1, RegistrationId rpk2, int numberOfDimensions)
        {
            if (rpk1.CachedEd25519publicKeySha256 == null)
            {
                rpk1.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rpk1.Ed25519publicKey);
            }
            var rpk1_ed25519publicKey_sha256 = rpk1.CachedEd25519publicKeySha256;

            if (rpk2.CachedEd25519publicKeySha256 == null)
            {
                rpk2.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rpk2.Ed25519publicKey);
            }
            var rpk2_ed25519publicKey_sha256 = rpk2.CachedEd25519publicKeySha256;

            if (rpk1_ed25519publicKey_sha256.Length != rpk2_ed25519publicKey_sha256.Length)
            {
                throw new ArgumentException();
            }
            _distance_sumSqr = 0;

            if (numberOfDimensions == 16)
            {
                fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256)
                {
                    ushort *rpk1aPtr = (ushort *)rpk1a, rpk2aPtr = (ushort *)rpk2a;
                    int     l = rpk1_ed25519publicKey_sha256.Length / 2;

                    for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++)
                    {
                        var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr);
                        _distance_sumSqr += d_i * d_i;
                    }
                }
            }
            else if (numberOfDimensions == 8)
            {
                fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256)
                {
                    uint *rpk1aPtr = (uint *)rpk1a, rpk2aPtr = (uint *)rpk2a;
                    int   l = rpk1_ed25519publicKey_sha256.Length / 4;

                    for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++)
                    {
                        var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr);
                        _distance_sumSqr += d_i * d_i;
                    }
                }
            }
            else if (numberOfDimensions == 4)
            {
                fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256)
                {
                    ulong *rpk1aPtr = (ulong *)rpk1a, rpk2aPtr = (ulong *)rpk2a;
                    int    l = rpk1_ed25519publicKey_sha256.Length / 8;

                    for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++)
                    {
                        var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr);
                        _distance_sumSqr += d_i * d_i;
                    }
                }
            }
            else if (numberOfDimensions == 2)
            {
                GetVectorValues_2(rpk1_ed25519publicKey_sha256, out var v1_0, out var v1_1);
                GetVectorValues_2(rpk2_ed25519publicKey_sha256, out var v2_0, out var v2_1);

                var d_0 = VectorComponentRoutine(v1_0, v2_0);
                var d_1 = VectorComponentRoutine(v1_1, v2_1);
                _distance_sumSqr += d_0 * d_0;
                _distance_sumSqr += d_1 * d_1;
            }
            else
            {
                throw new NotImplementedException();
            }
        }
예제 #17
0
        void RouteRegistrationRequest_LocalDrpPeerIteration(LocalDrpPeer localDrpPeer, RoutedRequest routedRequest,
                                                            ref double?maxP2pConnectionValue,
                                                            ref ConnectionToNeighbor proxyToDestinationPeer, ref LocalDrpPeer acceptAt)
        {
            var req = routedRequest.RegisterReq;
            var connectedNeighborsForRouting = localDrpPeer.GetConnectedNeighborsForRouting(routedRequest).ToList();
            var logger = routedRequest.Logger;

            var distancesToNeighbors         = new List <RegistrationIdDistance>();
            var requestedDirectionMulResults = new List <double>();
            int connectedNeighborsCountThatMatchReqFilters = 0;

            foreach (var neighbor in connectedNeighborsForRouting)
            {
                if (req.MinimalDistanceToNeighbor != 0)
                {
                    var distanceToNeighbor = req.RequesterRegistrationId.GetDistanceTo(_cryptoLibrary, neighbor.RemoteRegistrationId, NumberOfDimensions);
                    distancesToNeighbors.Add(distanceToNeighbor);
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"distanceToNeighbor={distanceToNeighbor} from REGISTER REQ {req.RequesterRegistrationId} to {neighbor} (req.min={req.MinimalDistanceToNeighbor})");
                    }
                    if (distanceToNeighbor.IsLessThan(req.MinimalDistanceToNeighbor))
                    {
                        // skip: this is too close than requested
                        if (logger.WriteToLog_detail_enabled)
                        {
                            logger.WriteToLog_detail($"skipping connection to {neighbor}: distance={distanceToNeighbor} is less than requested={req.MinimalDistanceToNeighbor}");
                        }
                        continue;
                    }
                }
                if (req.DirectionVectorNullable != null)
                {
                    var    requestedDirectionVector = req.DirectionVectorNullableD;
                    var    vectorFromThisToNeighbor = RegistrationId.GetDifferenceVector(req.RequesterRegistrationId, neighbor.RemoteRegistrationId, CryptoLibrary, Configuration.SandboxModeOnly_NumberOfDimensions);
                    double mulResult = 0;
                    for (int i = 0; i < requestedDirectionVector.Length; i++)
                    {
                        mulResult += requestedDirectionVector[i] * requestedDirectionVector[i];
                    }
                    requestedDirectionMulResults.Add(mulResult);
                    if (mulResult < 0)
                    {
                        if (logger.WriteToLog_detail_enabled)
                        {
                            logger.WriteToLog_detail($"skipping connection to {neighbor}: direction from requester to neighbor does not match requested vector");
                        }
                        continue;
                    }
                }
                connectedNeighborsCountThatMatchReqFilters++;

                var p2pConnectionValue_withNeighbor = P2pConnectionValueCalculator.GetMutualP2pConnectionValue(CryptoLibrary, req.RequesterRegistrationId, req.RequesterNeighborsBusySectorIds,
                                                                                                               neighbor.RemoteRegistrationId, neighbor.RemoteNeighborsBusySectorIds ?? 0, NumberOfDimensions, false, false, false);

                if (logger.WriteToLog_deepDetail_enabled)
                {
                    logger.WriteToLog_deepDetail($"p2pConnectionValue_withNeighbor={p2pConnectionValue_withNeighbor} from REGISTER REQ {req.RequesterRegistrationId} to {neighbor}");
                }

                if (maxP2pConnectionValue == null || maxP2pConnectionValue < p2pConnectionValue_withNeighbor)
                {
                    maxP2pConnectionValue  = p2pConnectionValue_withNeighbor;
                    proxyToDestinationPeer = neighbor;
                    acceptAt = null;
                }
            }

            if (connectedNeighborsCountThatMatchReqFilters == 0 && connectedNeighborsForRouting.Count != 0)
            {
                if (req.MinimalDistanceToNeighbor != 0)
                {
                    // special case: we are inside the "minDistance" hypersphere: move away from the requester, proxy to most distant neighbor
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"special case: move away from the requester, proxy to most distant neighbor");
                    }
                    RegistrationIdDistance maxDistance = null;
                    for (int i = 0; i < connectedNeighborsForRouting.Count; i++)
                    {
                        var neighbor           = connectedNeighborsForRouting[i];
                        var distanceToNeighbor = distancesToNeighbors[i];
                        if (logger.WriteToLog_detail_enabled)
                        {
                            logger.WriteToLog_detail($"distanceToConnectedPeer={distanceToNeighbor} from REGISTER REQ {req.RequesterRegistrationId} to {neighbor} (req.min={req.MinimalDistanceToNeighbor})");
                        }
                        if (maxDistance == null || distanceToNeighbor.IsGreaterThan(maxDistance))
                        {
                            maxDistance            = distanceToNeighbor;
                            proxyToDestinationPeer = neighbor;
                            acceptAt = null;
                        }
                    }
                }
                if (req.DirectionVectorNullable != null)
                {
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"special case: move towards the specified direction");
                    }
                    double?maxMulResult = null;
                    for (int i = 0; i < connectedNeighborsForRouting.Count; i++)
                    {
                        var neighbor  = connectedNeighborsForRouting[i];
                        var mulResult = requestedDirectionMulResults[i];
                        if (logger.WriteToLog_detail_enabled)
                        {
                            logger.WriteToLog_detail($"mulResult={mulResult} for {neighbor}");
                        }
                        if (maxMulResult == null || mulResult > maxMulResult)
                        {
                            maxMulResult           = mulResult;
                            proxyToDestinationPeer = neighbor;
                            acceptAt = null;
                        }
                    }
                }
            }

            // dont connect to local peer if already connected
            if (localDrpPeer.Configuration.LocalPeerRegistrationId.Equals(req.RequesterRegistrationId) == true)
            {
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"not accepting request at local peer: it has same regID {req.RequesterRegistrationId}");
                }
            }
            else if (localDrpPeer.ConnectedNeighbors.Any(x => x.RemoteRegistrationId.Equals(req.RequesterRegistrationId)) == true)
            {
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"not accepting request at local peer: already connected to {req.RequesterRegistrationId}");
                }
            }
            else if (localDrpPeer.ConnectedNeighbors.Count > localDrpPeer.Configuration.AbsoluteMaxNumberOfNeighbors)
            {
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"not accepting request at local peer: already too many neighbors ({localDrpPeer.ConnectedNeighbors.Count})");
                }
            }
            else
            {
                var p2pConnectionValue_withLocalPeer = P2pConnectionValueCalculator.GetMutualP2pConnectionValue(CryptoLibrary, req.RequesterRegistrationId, req.RequesterNeighborsBusySectorIds,
                                                                                                                localDrpPeer.Configuration.LocalPeerRegistrationId, localDrpPeer.ConnectedNeighborsBusySectorIds, NumberOfDimensions, false, false, false);
                if (logger.WriteToLog_detail_enabled)
                {
                    logger.WriteToLog_detail($"p2pConnectionValue_withLocalPeer={p2pConnectionValue_withLocalPeer} from REGISTER REQ {req.RequesterRegistrationId} to {localDrpPeer.Configuration.LocalPeerRegistrationId}");
                }
                if (maxP2pConnectionValue == null || p2pConnectionValue_withLocalPeer > maxP2pConnectionValue)
                {
                    maxP2pConnectionValue  = p2pConnectionValue_withLocalPeer;
                    proxyToDestinationPeer = null;
                    acceptAt = localDrpPeer;
                }
            }

            if (logger.WriteToLog_detail_enabled)
            {
                logger.WriteToLog_detail($"<< RouteRegistrationRequest_LocalDrpPeerIteration() proxyTo={proxyToDestinationPeer}, acceptAt={acceptAt}");
            }
        }
예제 #18
0
 internal bool PendingRegisterRequestExists(RegistrationId regId) => _pendingRegisterRequests.Contains(regId);
예제 #19
0
 public bool PendingInviteRequestExists(RegistrationId requesterRegId) => _pendingInviteRequests.Contains(requesterRegId);