Ejemplo n.º 1
0
        /// <summary>
        /// Creates CAN IPNS record object to point to a CAN object of the given hash with the given sequence number.
        /// </summary>
        /// <param name="Hash">Hash of the CAN object to point IPNS record to.</param>
        /// <param name="SequenceNumber">Sequence number of the IPNS record.</param>
        public CanIpnsEntry CreateIpnsRecord(byte[] Hash, UInt64 SequenceNumber)
        {
            log.Trace("(Hash:'{0}',SequenceNumber:{1})", Hash.ToBase58(), SequenceNumber);

            string validityString = DateTime.UtcNow.AddMonths(1).ToString(Rfc3339DateTimeFormat, DateTimeFormatInfo.InvariantInfo);

            byte[] validityBytes = Encoding.UTF8.GetBytes(validityString);

            UInt64 ttlNanoSec = (UInt64)(TimeSpan.FromSeconds(IpnsRecordExpirationTimeSeconds).TotalMilliseconds) * (UInt64)1000000;

            string valueString = CanApi.CreateIpfsPathFromHash(Hash);

            byte[] valueBytes = Encoding.UTF8.GetBytes(valueString);

            CanIpnsEntry res = new CanIpnsEntry()
            {
                Sequence     = SequenceNumber,
                ValidityType = CanIpnsEntry.Types.ValidityType.Eol,
                Ttl          = ttlNanoSec,
                Validity     = ProtocolHelper.ByteArrayToByteString(validityBytes),
                Value        = ProtocolHelper.ByteArrayToByteString(valueBytes)
            };

            res.Signature = ProtocolHelper.ByteArrayToByteString(CreateIpnsRecordSignature(res));

            log.Trace("(-):{0}", res);
            return(res);
        }
Ejemplo n.º 2
0
        public override bool Init()
        {
            log.Info("()");

            bool res = false;

            try
            {
                canApi = (CanApi)Base.ComponentDictionary["Network.ContentAddressNetwork.CanApi"];

                // Construct profile server's contact information CAN object.
                canContactInformation = new CanProfileServerContact()
                {
                    PublicKey   = ProtocolHelper.ByteArrayToByteString(Base.Configuration.Keys.PublicKey),
                    IpAddress   = ProtocolHelper.ByteArrayToByteString(Base.Configuration.ServerInterface.GetAddressBytes()),
                    PrimaryPort = (uint)Base.Configuration.ServerRoles.GetRolePort(ServerRole.Primary)
                };


                initThread = new Thread(new ThreadStart(InitThread));
                initThread.Start();

                res         = true;
                Initialized = true;
            }
            catch (Exception e)
            {
                log.Error("Exception occurred: {0}", e.ToString());
            }

            if (!res)
            {
                ShutdownSignaling.SignalShutdown();

                if ((initThread != null) && !initThreadFinished.WaitOne(25000))
                {
                    log.Error("Init thread did not terminated in 25 seconds.");
                }
            }

            log.Info("(-):{0}", res);
            return(res);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Refreshes profile server's IPNS record in CAN.
        /// </summary>
        /// <param name="IpnsRecord">IPNS record to refresh.</param>
        /// <param name="PublicKey">Public key of the IPNS record owner.</param>
        /// <returns>Structure describing whether the function succeeded and response provided by CAN server.</returns>
        public async Task <CanRefreshIpnsResult> RefreshIpnsRecord(CanIpnsEntry IpnsRecord, byte[] PublicKey)
        {
            log.Trace("(PublicKey:'{0}')", PublicKey.ToHex());

            string ipnsRecordEncoded = IpnsRecord.ToByteArray().ToBase64UrlPad(true);

            CanCryptoKey cryptoKey = new CanCryptoKey()
            {
                Type = CanCryptoKey.Types.KeyType.Ed25519,
                Data = ProtocolHelper.ByteArrayToByteString(PublicKey)
            };
            string keyEncoded = Base58Encoding.Encoder.Encode(cryptoKey.ToByteArray());

            log.Debug("Encoding public key: {0}", keyEncoded);

            NameValueCollection args = new NameValueCollection();

            args.Add("arg", ipnsRecordEncoded);
            args.Add("key", keyEncoded);

            CanApiResult apiResult = await SendRequest("name/upload", args);

            CanRefreshIpnsResult res = CanRefreshIpnsResult.FromApiResult(apiResult);

            if (res.Success)
            {
                res.IsCanError = false;

                // Check that the ID, path and sequence number match what we expect.
                string canId = CanApi.PublicKeyToId(PublicKey).ToBase58();
                if (res.Details.Peer == canId)
                {
                    string path = Encoding.UTF8.GetString(IpnsRecord.Value.ToByteArray());
                    if (res.Details.NewPath == path)
                    {
                        if (res.Details.NewSeq == IpnsRecord.Sequence)
                        {
                            // All OK.
                        }
                        else
                        {
                            log.Warn("CAN sequence is {0}, received {1}.", IpnsRecord.Sequence, res.Details.NewSeq);
                            res.Success = false;
                            res.Message = "CAN path in response does not match expected value.";
                        }
                    }
                    else
                    {
                        log.Warn("CAN path is '{0}', received '{1}'.", path, res.Details.NewPath);
                        res.Success = false;
                        res.Message = "CAN path in response does not match expected value.";
                    }
                }
                else
                {
                    log.Warn("CAN ID is '{0}', received '{1}'.", canId, res.Details.Peer);
                    res.Success = false;
                    res.Message = "CAN ID in response does not match expected value.";
                }
            }

            if (res.Success)
            {
                log.Trace("(-):*.Success={0}", res.Success);
            }
            else
            {
                log.Trace("(-):*.Success={0},*.IsCanError={1},*.Message='{2}'", res.Success, res.IsCanError, res.Message);
            }
            return(res);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Thread that is initializes CAN objects during the profile server startup.
        /// </summary>
        private async void InitThread()
        {
            log.Info("()");

            initThreadFinished.Reset();

            if (Base.Configuration.CanProfileServerContactInformationHash != null)
            {
                log.Debug("Old CAN object hash is '{0}', object {1} change.", Base.Configuration.CanProfileServerContactInformationHash.ToBase58(), Base.Configuration.CanProfileServerContactInformationChanged ? "DID" : "did NOT");
            }
            else
            {
                log.Debug("No CAN object found.");
            }

            bool deleteOldObject = Base.Configuration.CanProfileServerContactInformationChanged && (Base.Configuration.CanProfileServerContactInformationHash != null);

            byte[] canObject = canContactInformation.ToByteArray();
            log.Trace("CAN object: {0}", canObject.ToHex());

            while (!ShutdownSignaling.IsShutdown)
            {
                // First delete old CAN object if there is any.
                bool error = false;
                if (deleteOldObject)
                {
                    string          objectPath = CanApi.CreateIpfsPathFromHash(Base.Configuration.CanProfileServerContactInformationHash);
                    CanDeleteResult cres       = await canApi.CanDeleteObject(objectPath);

                    if (cres.Success)
                    {
                        log.Info("Old CAN object hash '{0}' deleted.", Base.Configuration.CanProfileServerContactInformationHash.ToBase58());
                    }
                    else
                    {
                        log.Warn("Failed to delete old CAN object hash '{0}', error message '{1}', will retry.", Base.Configuration.CanProfileServerContactInformationHash.ToBase58(), cres.Message);
                        error = true;
                    }
                }
                else
                {
                    log.Trace("No old object to delete.");
                }

                if (ShutdownSignaling.IsShutdown)
                {
                    break;
                }
                if (!error)
                {
                    if (Base.Configuration.CanProfileServerContactInformationChanged)
                    {
                        // Now upload the new object.
                        CanUploadResult cres = await canApi.CanUploadObject(canObject);

                        if (cres.Success)
                        {
                            canContactInformationHash = cres.Hash;
                            log.Info("New CAN object hash '{0}' added.", canContactInformationHash.ToBase58());
                            break;
                        }

                        log.Warn("Unable to add new object to CAN, error message: '{0}'", cres.Message);
                    }
                    else
                    {
                        canContactInformationHash = Base.Configuration.CanProfileServerContactInformationHash;
                        log.Info("CAN object unchanged since last time, hash is '{0}'.", canContactInformationHash.ToBase58());
                        break;
                    }
                }

                // Retry in 10 seconds.
                try
                {
                    await Task.Delay(10000, ShutdownSignaling.ShutdownCancellationTokenSource.Token);
                }
                catch
                {
                    // Catch cancellation exception.
                }
            }


            if (canContactInformationHash != null)
            {
                if (Base.Configuration.CanProfileServerContactInformationChanged)
                {
                    // Save the new data to the database.
                    if (!await SaveProfileServerContactInformation())
                    {
                        log.Error("Failed to save new profile server contact information values to database.");
                    }
                }

                // Finally, start IPNS record refreshing timer.
                await IpnsRecordRefresh();
            }


            initThreadFinished.Set();

            log.Info("(-)");
        }