Пример #1
0
        public static async ValueTask <DraftsBuilderFileRequest> CreateRequestAsync(
            Guid accountId,
            string fileName,
            DraftsBuilderDocumentFileData?builderData,
            IDocumentContentUploadStrategy?contentUploadStrategy,
            IContentService uploader,
            ICrypt crypt,
            TimeSpan?uploadTimeout)
        {
            if (string.IsNullOrWhiteSpace(fileName))
            {
                throw Errors.StringShouldNotBeNullOrWhiteSpace(nameof(fileName));
            }

            Guid?     contentId = null;
            Signature?signature = null;

            if (contentUploadStrategy is not null)
            {
                (contentId, signature) = await contentUploadStrategy.UploadAndSignAsync(accountId, uploader, crypt, uploadTimeout).ConfigureAwait(false);
            }

            return(new DraftsBuilderFileRequest(
                       contentId,
                       signature?.ToBase64String().ToString(),
                       new DraftsBuilderFileMetaRequest(fileName, builderData)
                       ));
        }
Пример #2
0
        private RuntimeParameterInfo(
            Signature signature,
            MetadataImport scope,
            int tkParamDef,
            int position,
            ParameterAttributes attributes,
            MemberInfo member
            )
        {
            Debug.Assert(member != null);
            Debug.Assert(
                MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport)
                );
            Debug.Assert(
                MdToken.IsNullToken(tkParamDef) ||
                MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef)
                );

            PositionImpl = position;
            MemberImpl   = member;
            m_signature  = signature;
            m_tkParamDef = MdToken.IsNullToken(tkParamDef)
              ? (int)MetadataTokenType.ParamDef
              : tkParamDef;
            m_scope   = scope;
            AttrsImpl = attributes;

            ClassImpl = null;
            NameImpl  = null;
        }
 public DataDeliveryReceipt(StatusCodes statusCode, uint consumedUnits, uint unpaidUnits, Signature signature)
 {
     StatusCode    = statusCode;
     ConsumedUnits = consumedUnits;
     UnpaidUnits   = unpaidUnits;
     Signature     = signature;
 }
        public async Task SignatureRepositoryTestsUpdateSignatureWorksForValidInput()
        {
            var inputSignature = new Signature {
                Signer = new User {
                    UserId = "007007", Name = "Bill"
                }
            };
            var       signatureRepository = new SignatureRepository();
            Signature?addedSignature      = await signatureRepository.AddSignature(inputSignature);

            bool initialSigningStatus = addedSignature.IsSigned;

            Assert.IsNotNull(addedSignature);
            var updateSignatureInput = new Signature {
                Id = addedSignature.Id, Signer = new User {
                    UserId = "007007", Name = "Bill G"
                }, IsSigned = true, SignedDateTime = DateTime.UtcNow, Text = "Bill G"
            };
            Signature?updatedSignature = await signatureRepository.UpdateSignature(updateSignatureInput);

            Assert.AreEqual(updateSignatureInput.Id, updatedSignature.Id);
            Assert.AreEqual(updatedSignature.SignedDateTime, updateSignatureInput.SignedDateTime);
            Assert.AreEqual(updatedSignature.Text, updateSignatureInput.Text);

            // Signer shouldn't be updated in SingatureRepository
            Assert.IsTrue(addedSignature.Signer.Equals(updateSignatureInput.Signer));
            Assert.IsTrue(updatedSignature.IsSigned);
            Assert.AreNotEqual(updatedSignature.IsSigned, initialSigningStatus);
        }
Пример #5
0
            public void ConvertsNullMethodToNullSignatureToSupportImplicitConversionRules()
            {
                Method <Signature>? @null  = null;
                Signature?          actual = @null;

                Assert.Null(actual);
            }
Пример #6
0
 public bool Equals(Signature?other)
 => other != null &&
 Comparison.AreStringValuesEqual(Content, other.Content) &&
 Equals(CurrentParameter, other.CurrentParameter) &&
 Comparison.AreStringValuesEqual(PrettyPrintedContent, other.PrettyPrintedContent) &&
 Comparison.AreStringValuesEqual(Documentation, other.Documentation) &&
 Comparison.AreArraysEqual(Parameters, other.Parameters);
Пример #7
0
        private bool ValidateSignature(Signature?signature, IReleaseSpec spec)
        {
            if (signature is null)
            {
                return(false);
            }

            BigInteger sValue = signature.SAsSpan.ToUnsignedBigInteger();
            BigInteger rValue = signature.RAsSpan.ToUnsignedBigInteger();

            if (sValue.IsZero || sValue >= (spec.IsEip2Enabled ? Secp256K1Curve.HalfN + 1 : Secp256K1Curve.N))
            {
                return(false);
            }

            if (rValue.IsZero || rValue >= Secp256K1Curve.N - 1)
            {
                return(false);
            }

            if (spec.IsEip155Enabled)
            {
                return((signature.ChainId ?? _chainIdValue) == _chainIdValue);
            }

            return(!spec.ValidateChainId || (signature.V == 27 || signature.V == 28));
        }
Пример #8
0
        public TransactionForRpc(Keccak?blockHash, long?blockNumber, int?txIndex, Transaction transaction)
        {
            Hash             = transaction.Hash;
            Nonce            = transaction.Nonce;
            BlockHash        = blockHash;
            BlockNumber      = blockNumber;
            TransactionIndex = txIndex;
            From             = transaction.SenderAddress;
            To         = transaction.To;
            Value      = transaction.Value;
            GasPrice   = transaction.GasPrice;
            Gas        = transaction.GasLimit;
            Input      = Data = transaction.Data;
            Type       = transaction.Type;
            AccessList = transaction.AccessList is null ? null : AccessListItemForRpc.FromAccessList(transaction.AccessList);

            Signature?signature = transaction.Signature;

            if (signature != null)
            {
                R = new UInt256(signature.R, true);
                S = new UInt256(signature.S, true);
                V = (UInt256?)signature.V;
            }
        }
 /// <inheritdoc />
 protected internal override bool VerifySignature(byte[] data, byte[] signature)
 {
     using (Signature? instance = Signature.GetInstance(GetSignatureName(this.Algorithm)))
     {
         Verify.Operation(instance is object, "Unable to get signature for algorithm: {0}", this.Algorithm);
         instance.InitVerify(this.publicKey);
         instance.Update(data);
         return(instance.Verify(signature));
     }
 }
Пример #10
0
 public SignalDescription(MethodInfo method, string name, Type actionType, Type signalType, Signature?signature, IList <ArgumentDescription> arguments, bool hasOnError)
 {
     MethodInfo       = method;
     Name             = name;
     ActionType       = actionType;
     SignalType       = signalType;
     SignalSignature  = signature;
     _signalArguments = arguments;
     HasOnError       = hasOnError;
 }
Пример #11
0
 public MethodDescription(MethodInfo member, string name, IList <ArgumentDescription> inArguments, Signature?inSignature, Type outType, bool isGenericOut, Signature?outSignature, IList <ArgumentDescription> outArguments)
 {
     MethodInfo    = member;
     Name          = name;
     _inArguments  = inArguments;
     InSignature   = inSignature;
     OutType       = outType;
     IsGenericOut  = isGenericOut;
     OutSignature  = outSignature;
     _outArguments = outArguments;
 }
 /// <inheritdoc />
 protected internal override byte[] Sign(byte[] data)
 {
     using (Signature? instance = Signature.GetInstance(GetSignatureName(this.Algorithm)))
     {
         Verify.Operation(instance is object, "Unable to get signature for algorithm: {0}", this.Algorithm);
         instance.InitSign(this.privateKey);
         instance.Update(data);
         byte[]? signature = instance.Sign();
         Assumes.NotNull(signature);
         return(signature);
     }
 }
Пример #13
0
 public bool Equals(Signature?other)
 {
     if (ReferenceEquals(null, other))
     {
         return(false);
     }
     if (ReferenceEquals(this, other))
     {
         return(true);
     }
     return(Core.Extensions.Bytes.AreEqual(Bytes, other.Bytes) && V == other.V);
 }
Пример #14
0
 public static Type AsType(this Signature?sig)
 {
     if (!sig.HasValue)
     {
         return(typeof(void));
     }
     if (sig.Value.IsSingleCompleteType)
     {
         return(sig.Value.ToType());
     }
     throw new Exception("Non-single-complete data types not supported yet");
 }
Пример #15
0
 public MevMegabundle(long blockNumber, IReadOnlyList <BundleTransaction> transactions, Keccak[]?revertingTxHashes = null,
                      Signature?relaySignature = null, UInt256?minTimestamp = null, UInt256?maxTimestamp = null)
     : base(blockNumber, transactions, minTimestamp, maxTimestamp)
 {
     RelaySignature    = relaySignature;
     RevertingTxHashes = revertingTxHashes ?? Array.Empty <Keccak>();
     Hash = GetHash(this);
     for (int i = 0; i < transactions.Count; i++)
     {
         transactions[i].BundleHash = Hash;
     }
 }
Пример #16
0
        public bool AddShare(int idx, Signature sigShare, out Signature?result)
        {
            result = null;
            if (idx < 0 || idx >= _publicKeySet.Count)
            {
                Logger.LogWarning($"Public key (?) is not recognized (index {idx})");
                return(false);
            }

            var pubKey = _publicKeySet[idx];

            if (_collectedShares[idx] != null)
            {
                Logger.LogWarning($"Signature share {idx} input twice");
                if (sigShare != _collectedShares[idx])
                {
                    return(false);
                }
                _collectedSharesNumber--; // to compensate increment later
            }

            if (!IsShareValid(pubKey, sigShare))
            {
                Logger.LogWarning($"Signature share {idx} is not valid: {sigShare.ToHex()}");
                return(false);
            }

            if (_collectedSharesNumber > _publicKeySet.Threshold)
            {
                result = _signature;
                return(true);
            }

            Logger.LogTrace($"Collected signature share #{idx}: {sigShare.RawSignature.ToHex()}");
            _collectedShares[idx]   = sigShare;
            _collectedSharesNumber += 1;
            if (_collectedSharesNumber <= _publicKeySet.Threshold)
            {
                return(true);
            }
            var signature = CombineBenchmark.Benchmark(() => _publicKeySet.AssembleSignature(
                                                           _collectedShares.Select((share, i) => new KeyValuePair <int, Signature>(i, share))
                                                           .Where(pair => pair.Value != null).ToArray()
                                                           ));

            if (!_publicKeySet.SharedPublicKey.ValidateSignature(signature, _dataToSign))
            {
                throw new Exception("Fatal error: all shares are valid but combined signature is not");
            }
            _signature = signature;
            result     = signature;
            return(true);
        }
        public async Task SignatureRepositoryTestsAddSignatureCreatesNewGuid()
        {
            var inputSignatureId = Guid.NewGuid();
            var inputSignature   = new Signature {
                Id = inputSignatureId
            };
            var       signatureRepository = new SignatureRepository();
            Signature?addedSignature      = await signatureRepository.AddSignature(inputSignature);

            Assert.AreNotEqual(inputSignatureId, addedSignature.Id);
            Assert.IsFalse(addedSignature.IsSigned);
        }
        public async Task SignatureRepositoryTestsGetSignatureThrowsApiExceptionForInvalidInput()
        {
            var inputSignature = new Signature {
                Signer = new User {
                    UserId = "007007"
                }
            };
            var       signatureRepository = new SignatureRepository();
            Signature?addedSignature      = await signatureRepository.AddSignature(inputSignature);

            Assert.IsNotNull(addedSignature);

            await signatureRepository.GetSignature(Guid.NewGuid());
        }
Пример #19
0
 public ThresholdSigner(IEnumerable <byte> dataToSign, PrivateKeyShare privateKeyShare, PublicKeySet publicKeySet)
 {
     if (!publicKeySet.Keys.Contains(privateKeyShare.GetPublicKeyShare()))
     {
         throw new ArgumentException(
                   "Invalid private key share for threshold signature: " +
                   "corresponding public key is not in keyring"
                   );
     }
     _dataToSign            = dataToSign.ToArray();
     _privateKeyShare       = privateKeyShare;
     _publicKeySet          = publicKeySet;
     _collectedShares       = new Signature[publicKeySet.Count];
     _collectedSharesNumber = 0;
     _signature             = null;
 }
        public async Task SignatureRepositoryTestsGetSignatureRetrievesMatchingRecordForValidInput()
        {
            var inputSignature = new Signature {
                Signer = new User {
                    UserId = "007007", Name = "Bill"
                }
            };
            var       signatureRepository = new SignatureRepository();
            Signature?addedSignature      = await signatureRepository.AddSignature(inputSignature);

            Signature?retrievedSignature = await signatureRepository.GetSignature(addedSignature.Id);

            Assert.IsNotNull(retrievedSignature);
            Assert.AreEqual(addedSignature.Id, retrievedSignature.Id);
            Assert.IsTrue(addedSignature.Signer.Equals(retrievedSignature.Signer));
        }
Пример #21
0
        public SignatureInfo(Signature signature)
        {
            _signature = signature ?? throw new ArgumentNullException(nameof(signature));

            try
            {
                Type = signature.Type;
#pragma warning disable CA1826 // Do not use Enumerable methods on indexable collections. Instead use the collection directly
                var ts = signature.Timestamps.FirstOrDefault();
#pragma warning restore CA1826 // Do not use Enumerable methods on indexable collections. Instead use the collection directly

                Timestamp           = ts?.GeneralizedTime;
                TimestampSignerInfo = ts?.SignerInfo;
            }
            catch (CryptographicException) // possibly a malformed timestamp
            {
            }
        }
        public async Task SignatureRepositoryTestsUpdateSignatureThrowsApiExceptionForSingingComplete()
        {
            var inputSignature = new Signature {
                Signer = new User {
                    UserId = "007007", Name = "Bill"
                }, IsSigned = true
            };
            var       signatureRepository = new SignatureRepository();
            Signature?addedSignature      = await signatureRepository.AddSignature(inputSignature);

            Assert.IsNotNull(addedSignature);

            var updateSignatureInput = new Signature {
                Signer = new User {
                    UserId = "007007", Name = "Bill"
                }, IsSigned = false
            };
            await signatureRepository.UpdateSignature(updateSignatureInput);
        }
Пример #23
0
        protected internal void EmitNonVoidSignal(string iface, string member, Signature?inSigStr, MessageWriter writer)
        {
            if (!IsRegistered)
            {
                return;
            }

            Message signalMsg = new Message(
                new Header(MessageType.Signal)
            {
                Path      = _objectPath,
                Interface = iface,
                Member    = member,
                Signature = inSigStr
            },
                writer?.ToArray(),
                writer?.UnixFds
                );

            _connection.EmitSignal(signalMsg);
        }
Пример #24
0
        public static TransactionChainId GetEthTx(this Transaction t, Signature?s, bool useNewId)
        {
            var nonce = t.Nonce == 0
                ? Array.Empty <byte>()
                : new BigInteger(t.Nonce).ToByteArray().Reverse().ToArray().TrimLeadingZeros();
            var sig = s is null?Array.Empty <byte>() : s.Encode().AsSpan();

            var ethTx = new Nethereum.Signer.TransactionChainId(
                nonce,
                new BigInteger(t.GasPrice).ToByteArray().Reverse().ToArray().TrimLeadingZeros(),
                new BigInteger(t.GasLimit).ToByteArray().Reverse().ToArray().TrimLeadingZeros(),
                t.To.ToBytes(), // this may be empty, same as passing null
                t.Value.ToBytes(false, true),
                t.Invocation.ToArray(),
                new BigInteger(ChainId(useNewId)).ToByteArray().Reverse().ToArray().TrimLeadingZeros(),
                sig.IsEmpty ? Array.Empty <byte>() : sig.Slice(0, 32).ToArray().TrimLeadingZeros(),
                sig.IsEmpty ? Array.Empty <byte>() : sig.Slice(32, 32).ToArray().TrimLeadingZeros(),
                sig.IsEmpty ? Array.Empty <byte>() : sig.Slice(64, sig.Length - 64).ToArray().TrimLeadingZeros()
                );

            return(ethTx);
        }
Пример #25
0
        public TransactionForRpc(Keccak?blockHash, long?blockNumber, int?txIndex, Transaction transaction, UInt256?baseFee = null)
        {
            Hash             = transaction.Hash;
            Nonce            = transaction.Nonce;
            BlockHash        = blockHash;
            BlockNumber      = blockNumber;
            TransactionIndex = txIndex;
            From             = transaction.SenderAddress;
            To       = transaction.To;
            Value    = transaction.Value;
            GasPrice = transaction.GasPrice;
            Gas      = transaction.GasLimit;
            Input    = Data = transaction.Data;
            if (transaction.IsEip1559)
            {
                GasPrice = baseFee != null
                    ? transaction.CalculateEffectiveGasPrice(true, baseFee.Value)
                    : transaction.MaxFeePerGas;

                MaxFeePerGas         = transaction.MaxFeePerGas;
                MaxPriorityFeePerGas = transaction.MaxPriorityFeePerGas;
            }
            ChainId    = transaction.ChainId;
            Type       = transaction.Type;
            AccessList = transaction.AccessList is null ? null : AccessListItemForRpc.FromAccessList(transaction.AccessList);

            Signature?signature = transaction.Signature;

            if (signature != null)
            {
                YParity = (transaction.IsEip1559 || transaction.IsEip2930) ? signature.RecoveryId : null;
                R       = new UInt256(signature.R, true);
                S       = new UInt256(signature.S, true);
                V       = transaction.Type == TxType.Legacy ? (UInt256?)signature.V : (UInt256?)signature.RecoveryId;
            }
        }
Пример #26
0
 public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Signature?value)
 => context.Writer.WriteString(value?.ToString() ?? string.Empty);
Пример #27
0
        protected internal async Task <Message> CreateNonVoidReply <T>(Message methodCall, Task <T> resultTask, Action <MessageWriter, T> writeResult, Signature?outSignature)
        {
            uint serial = methodCall.Header.Serial;

            T result = await resultTask.ConfigureAwait(false);

            MessageWriter retWriter = new MessageWriter();

            writeResult(retWriter, result);

            Message replyMsg = new Message(
                new Header(MessageType.MethodReturn)
            {
                Signature = outSignature
            },
                retWriter.ToArray(),
                retWriter.UnixFds
                );

            return(replyMsg);
        }
Пример #28
0
        private static void InspectParameterType(Type parameterType, ParameterInfo parameter, out Signature?signature, out IList <ArgumentDescription> arguments)
        {
            var  argumentAttribute = parameter.GetCustomAttribute <ArgumentAttribute>(false);
            bool isValueTuple;

            arguments = new List <ArgumentDescription>();
            if (argumentAttribute != null)
            {
                signature = Signature.GetSig(parameterType, isCompileTimeType: true);
                arguments.Add(new ArgumentDescription(argumentAttribute.Name, signature.Value, parameterType));
            }
            else if (IsStructType(parameterType, out isValueTuple))
            {
                signature = null;
                var            fields            = ArgTypeInspector.GetStructFields(parameterType, isValueTuple);
                IList <string> tupleElementNames = null;
                if (isValueTuple)
                {
                    var tupleElementNamesAttribute = parameter.GetCustomAttribute <TupleElementNamesAttribute>(false);
                    if (tupleElementNamesAttribute != null)
                    {
                        tupleElementNames = tupleElementNamesAttribute.TransformNames;
                    }
                }
                int nameIdx = 0;
                for (int i = 0; i < fields.Length;)
                {
                    var field     = fields[i];
                    var fieldType = field.FieldType;
                    if (i == 7 && isValueTuple)
                    {
                        fields = ArgTypeInspector.GetStructFields(fieldType, isValueTuple);
                        i      = 0;
                    }
                    else
                    {
                        var argumentSignature = Signature.GetSig(fieldType, isCompileTimeType: true);
                        var name = tupleElementNames != null && tupleElementNames.Count > nameIdx ? tupleElementNames[nameIdx] : field.Name;
                        arguments.Add(new ArgumentDescription(name, argumentSignature, fieldType));
                        if (signature == null)
                        {
                            signature = argumentSignature;
                        }
                        else
                        {
                            signature = Signature.Concat(signature.Value, argumentSignature);
                        }
                        i++;
                        nameIdx++;
                    }
                }
            }
            else
            {
                signature = Signature.GetSig(parameterType, isCompileTimeType: true);
                arguments.Add(new ArgumentDescription("value", signature.Value, parameterType));
            }
        }
Пример #29
0
        private static void AddInterfaceDescription(Type type, DBusInterfaceAttribute interfaceAttribute, List <InterfaceDescription> interfaces)
        {
            if (interfaces.Any(interf => interf.Name == interfaceAttribute.Name))
            {
                throw new ArgumentException($"DBus interface {interfaceAttribute.Name} is inherited multiple times");
            }

            IList <MethodDescription>   methods                 = null;
            IList <SignalDescription>   signals                 = null;
            IList <PropertyDescription> properties              = null;
            MethodDescription           propertyGetMethod       = null;
            MethodDescription           propertySetMethod       = null;
            MethodDescription           propertyGetAllMethod    = null;
            SignalDescription           propertiesChangedSignal = null;
            Type propertyType = interfaceAttribute.PropertyType;
            Type elementType;

            if (propertyType != null && ArgTypeInspector.InspectEnumerableType(propertyType, out elementType, isCompileTimeType: true) != ArgTypeInspector.EnumerableType.AttributeDictionary)
            {
                throw new ArgumentException($"Property type '{propertyType.FullName}' does not have the '{typeof(DictionaryAttribute).FullName}' attribute");
            }

            foreach (var member in type.GetMethods())
            {
                string memberName = member.ToString();
                if (!member.Name.EndsWith("Async", StringComparison.Ordinal))
                {
                    throw new ArgumentException($"{memberName} does not end with 'Async'");
                }
                var isSignal = member.Name.StartsWith("Watch", StringComparison.Ordinal);
                if (isSignal)
                {
                    if (member.ReturnType != s_signalReturnType)
                    {
                        throw new ArgumentException($"Signal {memberName} does not return 'Task<IDisposable>'");
                    }

                    var name = member.Name.Substring(5, member.Name.Length - 10);
                    if (name.Length == 0)
                    {
                        throw new ArgumentException($"Signal {memberName} has an empty name");
                    }

                    Signature?parameterSignature          = null;
                    IList <ArgumentDescription> arguments = null;
                    var  parameters           = member.GetParameters();
                    var  actionParameter      = parameters.Length > 0 ? parameters[0] : null;
                    Type parameterType        = null;
                    bool validActionParameter = false;
                    if (actionParameter != null)
                    {
                        if (actionParameter.ParameterType == s_exceptionActionType)
                        {
                            // actionParameter is missing
                        }
                        else if (actionParameter.ParameterType == s_emptyActionType)
                        {
                            validActionParameter = true;
                        }
                        else if (actionParameter.ParameterType.GetTypeInfo().IsGenericType &&
                                 actionParameter.ParameterType.GetGenericTypeDefinition() == s_singleParameterActionType)
                        {
                            validActionParameter = true;
                            parameterType        = actionParameter.ParameterType.GetGenericArguments()[0];
                            InspectParameterType(parameterType, actionParameter, out parameterSignature, out arguments);
                        }
                    }
                    if (parameters.Length > 0 && parameters[parameters.Length - 1].ParameterType == s_cancellationTokenType)
                    {
                        throw new NotSupportedException($"Signal {memberName} does not support cancellation. See https://github.com/tmds/Tmds.DBus/issues/15.");
                    }
                    var  lastParameter = parameters.Length > 0 ? parameters[parameters.Length - 1] : null;
                    bool hasOnError    = lastParameter?.ParameterType == s_exceptionActionType;
                    if (!validActionParameter || parameters.Length != 1 + (hasOnError ? 1 : 0))
                    {
                        throw new ArgumentException($"Signal {memberName} must accept an argument of Type 'Action'/'Action<>' and optional argument of Type 'Action<Exception>'");
                    }

                    var signal = new SignalDescription(member, name, actionParameter.ParameterType, parameterType, parameterSignature, arguments, hasOnError);
                    if (member.Name == interfaceAttribute.WatchPropertiesMethod)
                    {
                        if (propertiesChangedSignal != null)
                        {
                            throw new ArgumentException($"Multiple property changes signals are declared: {memberName}, {propertyGetMethod.MethodInfo.ToString()}");
                        }
                        propertiesChangedSignal = signal;
                        if (propertiesChangedSignal.SignalSignature != s_propertiesChangedSignature)
                        {
                            throw new ArgumentException($"PropertiesChanged signal {memberName} must accept an Action<T> where T is a struct with an IDictionary<string, object> and an string[] field");
                        }
                    }
                    else
                    {
                        signals = signals ?? new List <SignalDescription>();
                        signals.Add(signal);
                    }
                }
                else
                {
                    var name = member.Name.Substring(0, member.Name.Length - 5);
                    if (name.Length == 0)
                    {
                        throw new ArgumentException($"DBus Method {memberName} has an empty name");
                    }

                    IList <ArgumentDescription> outArguments = null;
                    Signature?outSignature  = null;
                    var       taskParameter = member.ReturnType;
                    Type      outType       = null;
                    bool      valid         = false;
                    bool      isGenericOut  = false;
                    if (taskParameter != null)
                    {
                        if (taskParameter == s_emptyTaskType)
                        {
                            valid   = true;
                            outType = null;
                        }
                        else if (taskParameter.GetTypeInfo().IsGenericType &&
                                 taskParameter.GetGenericTypeDefinition() == s_parameterTaskType)
                        {
                            valid   = true;
                            outType = taskParameter.GetGenericArguments()[0];
                            if (outType.IsGenericParameter)
                            {
                                outType      = s_objectType;
                                isGenericOut = true;
                            }
                            InspectParameterType(outType, member.ReturnParameter, out outSignature, out outArguments);
                        }
                    }
                    if (!valid)
                    {
                        throw new ArgumentException($"DBus Method {memberName} does not return 'Task'/'Task<>'");
                    }

                    IList <ArgumentDescription> inArguments = null;
                    Signature?inSignature = null;
                    var       parameters  = member.GetParameters();
                    if (parameters.Length > 0 && parameters[parameters.Length - 1].ParameterType == s_cancellationTokenType)
                    {
                        throw new NotSupportedException($"DBus Method {memberName} does not support cancellation. See https://github.com/tmds/Tmds.DBus/issues/15.");
                    }

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        var param          = parameters[i];
                        var parameterType  = param.ParameterType;
                        var paramSignature = Signature.GetSig(parameterType, isCompileTimeType: true);
                        if (inSignature == null)
                        {
                            inSignature = paramSignature;
                        }
                        else
                        {
                            inSignature = Signature.Concat(inSignature.Value, paramSignature);
                        }
                        inArguments = inArguments ?? new List <ArgumentDescription>();
                        var argumentAttribute = param.GetCustomAttribute <ArgumentAttribute>(false);
                        var argName           = argumentAttribute != null ? argumentAttribute.Name : param.Name;
                        inArguments.Add(new ArgumentDescription(argName, paramSignature, parameterType));
                    }

                    var methodDescription = new MethodDescription(member, name, inArguments, inSignature, outType, isGenericOut, outSignature, outArguments);
                    if (member.Name == interfaceAttribute.GetPropertyMethod)
                    {
                        if (propertyGetMethod != null)
                        {
                            throw new ArgumentException($"Multiple property Get methods are declared: {memberName}, {propertyGetMethod.MethodInfo.ToString()}");
                        }
                        propertyGetMethod = methodDescription;
                        if ((propertyGetMethod.InSignature != Signature.StringSig) ||
                            (propertyGetMethod.OutSignature != Signature.VariantSig))
                        {
                            throw new ArgumentException($"Property Get method {memberName} must accept a 'string' parameter and return 'Task<object>'");
                        }
                    }
                    else if (member.Name == interfaceAttribute.GetAllPropertiesMethod)
                    {
                        if (propertyGetAllMethod != null)
                        {
                            throw new ArgumentException($"Multiple property GetAll are declared: {memberName}, {propertyGetAllMethod.MethodInfo.ToString()}");
                        }
                        propertyGetAllMethod = methodDescription;
                        if ((propertyGetAllMethod.InArguments.Count != 0) ||
                            (propertyGetAllMethod.OutSignature != s_getAllOutSignature))
                        {
                            throw new ArgumentException($"Property GetAll method {memberName} must accept no parameters and return 'Task<IDictionary<string, object>>'");
                        }
                        if (propertyType == null)
                        {
                            if (ArgTypeInspector.InspectEnumerableType(methodDescription.OutType, out elementType, isCompileTimeType: true) == ArgTypeInspector.EnumerableType.AttributeDictionary)
                            {
                                propertyType = methodDescription.OutType;
                            }
                        }
                    }
                    else if (member.Name == interfaceAttribute.SetPropertyMethod)
                    {
                        if (propertySetMethod != null)
                        {
                            throw new ArgumentException($"Multiple property Set are declared: {memberName}, {propertySetMethod.MethodInfo.ToString()}");
                        }
                        propertySetMethod = methodDescription;
                        if ((propertySetMethod.InArguments?.Count != 2 || propertySetMethod.InArguments[0].Type != s_stringType || propertySetMethod.InArguments[1].Type != s_objectType) ||
                            (propertySetMethod.OutArguments.Count != 0))
                        {
                            throw new ArgumentException($"Property Set method {memberName} must accept a 'string' and 'object' parameter and return 'Task'");
                        }
                    }
                    else
                    {
                        methods = methods ?? new List <MethodDescription>();
                        methods.Add(methodDescription);
                    }
                }
            }
            if (propertyType != null)
            {
                var fields = propertyType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (var field in fields)
                {
                    string propertyName;
                    Type   fieldType;
                    PropertyTypeInspector.InspectField(field, out propertyName, out fieldType);
                    var propertySignature = Signature.GetSig(fieldType, isCompileTimeType: true);
                    var propertyAccess    = field.GetCustomAttribute <PropertyAttribute>()?.Access ?? PropertyAccess.ReadWrite;
                    var description       = new PropertyDescription(propertyName, propertySignature, propertyAccess);
                    properties = properties ?? new List <PropertyDescription>();
                    properties.Add(description);
                }
            }
            interfaces.Add(new InterfaceDescription(type, interfaceAttribute.Name, methods, signals, properties,
                                                    propertyGetMethod, propertyGetAllMethod, propertySetMethod, propertiesChangedSignal));
        }
Пример #30
0
 // used by RuntimePropertyInfo
 internal RuntimeParameterInfo(RuntimeParameterInfo accessor, RuntimePropertyInfo property)
     : this(accessor, (MemberInfo)property)
 {
     m_signature = property.Signature;
 }