예제 #1
0
 /// <summary>
 /// Add a procedure to the service
 /// </summary>
 void AddProcedure(ProcedureSignature signature)
 {
     if (Procedures.ContainsKey(signature.Name))
     {
         throw new ServiceException("Service " + Name + " contains duplicate procedures " + signature.Name);
     }
     Procedures [signature.Name] = signature;
 }
예제 #2
0
파일: RPCException.cs 프로젝트: 602p/krpc
 public RPCException(ProcedureSignature procedure, Exception exception)
 {
     if (VerboseErrors) {
         message = "'" + procedure.FullyQualifiedName + "' threw an exception.";
         message += " " + exception.GetType () + ": " + exception.Message;
     } else {
         message = exception.Message;
     }
 }
예제 #3
0
 public RPCException (ProcedureSignature procedure, string message)
 {
     if (VerboseErrors) {
         description = "'" + procedure.FullyQualifiedName + "' threw an exception.\n";
         description += GetType () + ": " + message;
     } else {
         description = message;
     }
 }
예제 #4
0
파일: RPCException.cs 프로젝트: 602p/krpc
 public RPCException(ProcedureSignature procedure, string message)
 {
     if (VerboseErrors) {
         this.message = "'" + procedure.FullyQualifiedName + "' threw an exception.";
         this.message += " " + GetType () + ": " + message;
     } else {
         this.message = message;
     }
 }
예제 #5
0
 public RPCException (ProcedureSignature procedure, Exception innerException)
 {
     var innerMessage = innerException.Message;
     if (VerboseErrors) {
         description = "'" + procedure.FullyQualifiedName + "' threw an exception.\n";
         description += innerException.GetType () + ": " + innerMessage + "\n" + innerException.StackTrace;
     } else {
         description = innerMessage;
     }
 }
예제 #6
0
파일: Services.cs 프로젝트: BasConijn/krpc
 /// <summary>
 /// Executes the given request and returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response.Builder HandleRequest(ProcedureSignature procedure, Request request)
 {
     object[] arguments = DecodeArguments (procedure, request.ArgumentsList);
     object returnValue;
     try {
         returnValue = procedure.Handler.Invoke (arguments);
     } catch (TargetInvocationException e) {
         if (e.InnerException.GetType () == typeof(YieldException))
             throw e.InnerException;
         throw new RPCException ("Procedure '" + procedure.FullyQualifiedName + "' threw an exception. " +
         e.InnerException.GetType () + ": " + e.InnerException.Message + "\n" + e.InnerException.StackTrace);
     }
     var responseBuilder = Response.CreateBuilder ();
     if (procedure.HasReturnType)
         responseBuilder.ReturnValue = EncodeReturnValue (procedure, returnValue);
     return responseBuilder;
 }
예제 #7
0
파일: Services.cs 프로젝트: paperclip/krpc
 public Response HandleRequest (ProcedureSignature procedure, object[] arguments)
 {
     if ((CallContext.GameScene & procedure.GameScene) == 0)
         throw new RPCException (procedure, "Procedure not available in game scene '" + CallContext.GameScene + "'");
     object returnValue;
     try {
         returnValue = procedure.Handler.Invoke (arguments);
     } catch (TargetInvocationException e) {
         if (e.InnerException is YieldException)
             throw e.InnerException;
         throw new RPCException (procedure, e.InnerException);
     }
     var response = new Response ();
     if (procedure.HasReturnType) {
         CheckReturnValue (procedure, returnValue);
         response.ReturnValue = returnValue;
     }
     return response;
 }
예제 #8
0
파일: Services.cs 프로젝트: 602p/krpc
        /// <summary>
        /// Decode a serialized collection
        /// </summary>
        object DecodeCollection(ProcedureSignature procedure, int i, Type type, ByteString value)
        {
            if (TypeUtils.IsAListCollectionType (type)) {
                var builder = Schema.KRPC.List.CreateBuilder ();
                var encodedList = builder.MergeFrom (value).Build ();
                var list = (System.Collections.IList)(typeof(System.Collections.Generic.List<>)
                    .MakeGenericType (type.GetGenericArguments ().Single ())
                    .GetConstructor (Type.EmptyTypes)
                    .Invoke (null));
                foreach (var item in encodedList.ItemsList)
                    list.Add (Decode (procedure, i, type.GetGenericArguments ().Single (), item));
                return list;
            } else if (TypeUtils.IsADictionaryCollectionType (type)) {
                var builder = Schema.KRPC.Dictionary.CreateBuilder ();
                var encodedDictionary = builder.MergeFrom (value).Build ();
                var dictionary = (System.Collections.IDictionary)(typeof(System.Collections.Generic.Dictionary<,>)
                    .MakeGenericType (type.GetGenericArguments () [0], type.GetGenericArguments () [1])
                    .GetConstructor (Type.EmptyTypes)
                    .Invoke (null));
                foreach (var entry in encodedDictionary.EntriesList) {
                    var k = Decode (procedure, i, type.GetGenericArguments () [0], entry.Key);
                    var v = Decode (procedure, i, type.GetGenericArguments () [1], entry.Value);
                    dictionary [k] = v;
                }
                return dictionary;
            } else if (TypeUtils.IsASetCollectionType (type)) {
                var builder = Schema.KRPC.Set.CreateBuilder ();
                var encodedSet = builder.MergeFrom (value).Build ();

                var set = (System.Collections.IEnumerable)(typeof(System.Collections.Generic.HashSet<>)
                    .MakeGenericType (type.GetGenericArguments ().Single ())
                    .GetConstructor (Type.EmptyTypes)
                    .Invoke (null));

                MethodInfo methodInfo = type.GetMethod ("Add");

                foreach (var item in encodedSet.ItemsList) {
                    var decodedItem = Decode (procedure, i, type.GetGenericArguments ().Single (), item);
                    methodInfo.Invoke (set, new [] { decodedItem });
                }
                return set;
            } else { // a tuple
                // TODO: this is ugly

                var builder = Schema.KRPC.Tuple.CreateBuilder ();
                var encodedTuple = builder.MergeFrom (value).Build ();
                var valueTypes = type.GetGenericArguments ().ToArray ();
                var genericType = Type.GetType ("KRPC.Utils.Tuple`" + valueTypes.Length);

                Object[] values = new Object[valueTypes.Length];
                for (int j = 0; j < valueTypes.Length; j++) {
                    var item = encodedTuple.ItemsList [j];
                    values [j] = Decode (procedure, i, valueTypes [j], item);
                }

                var tuple = genericType
                    .MakeGenericType (valueTypes)
                    .GetConstructor (valueTypes)
                    .Invoke (values);
                return tuple;
            }
        }
예제 #9
0
파일: Services.cs 프로젝트: paperclip/krpc
        public object[] GetArguments (ProcedureSignature procedure, IList<Argument> arguments)
        {
            // Get list of supplied argument values and whether they were set
            var numParameters = procedure.Parameters.Count;
            var argumentValues = new object [numParameters];
            var argumentSet = new BitVector32 (0);
            foreach (var argument in arguments) {
                argumentValues [argument.Position] = argument.Value;
                argumentSet [1 << (int)argument.Position] = true;
            }

            var mask = BitVector32.CreateMask ();
            for (int i = 0; i < numParameters; i++) {
                var value = argumentValues [i];
                var parameter = procedure.Parameters [i];
                var type = parameter.Type;
                if (!argumentSet [mask]) {
                    // If the argument is not set, set it to the default value
                    if (!parameter.HasDefaultValue)
                        throw new RPCException (procedure, "Argument not specified for parameter " + parameter.Name + " in " + procedure.FullyQualifiedName + ". ");
                    argumentValues [i] = parameter.DefaultValue;
                } else if (value != null && !type.IsInstanceOfType (value)) {
                    // Check the type of the non-null argument value
                    throw new RPCException (
                        procedure,
                        "Incorrect argument type for parameter " + parameter.Name + " in " + procedure.FullyQualifiedName + ". " +
                        "Expected an argument of type " + type + ", got " + value.GetType ());
                } else if (value == null && !TypeUtils.IsAClassType (type)) {
                    // Check the type of the null argument value
                    throw new RPCException (
                        procedure,
                        "Incorrect argument type for parameter " + parameter.Name + " in " + procedure.FullyQualifiedName + ". " +
                        "Expected an argument of type " + type + ", got null");
                }
                mask = BitVector32.CreateMask (mask);
            }
            return argumentValues;
        }
예제 #10
0
파일: Services.cs 프로젝트: paperclip/krpc
 /// <summary>
 /// Check the value returned by a procedure handler.
 /// </summary>
 static void CheckReturnValue (ProcedureSignature procedure, object returnValue)
 {
     // Check if the type of the return value is valid
     if (returnValue != null && !procedure.ReturnType.IsInstanceOfType (returnValue)) {
         throw new RPCException (
             procedure,
             "Incorrect value returned by " + procedure.FullyQualifiedName + ". " +
             "Expected a value of type " + procedure.ReturnType + ", got " + returnValue.GetType ());
     } else if (returnValue == null && !TypeUtils.IsAClassType (procedure.ReturnType)) {
         throw new RPCException (
             procedure,
             "Incorrect value returned by " + procedure.FullyQualifiedName + ". " +
             "Expected a value of type " + procedure.ReturnType + ", got null");
     }
 }
예제 #11
0
 /// <summary>
 /// Add a procedure to the service
 /// </summary>
 void AddProcedure(ProcedureSignature signature)
 {
     if (Procedures.ContainsKey (signature.Name))
         throw new ServiceException ("Service " + Name + " contains duplicate procedures " + signature.Name);
     Procedures [signature.Name] = signature;
 }
예제 #12
0
파일: Services.cs 프로젝트: paperclip/krpc
 /// <summary>
 /// Executes the given request and returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response HandleRequest (ProcedureSignature procedure, Request request)
 {
     return HandleRequest (procedure, GetArguments (procedure, request.Arguments));
 }
예제 #13
0
파일: Services.cs 프로젝트: 602p/krpc
 /// <summary>
 /// Executes a request (from an array of decoded arguments) and returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response.Builder HandleRequest(ProcedureSignature procedure, object[] arguments)
 {
     if ((KRPCServer.Context.GameScene & procedure.GameScene) == 0)
         throw new RPCException (procedure, "Procedure not available in game scene '" + KRPCServer.Context.GameScene + "'");
     object returnValue;
     try {
         returnValue = procedure.Handler.Invoke (arguments);
     } catch (TargetInvocationException e) {
         if (e.InnerException.GetType () == typeof(YieldException))
             throw e.InnerException;
         throw new RPCException (procedure, e.InnerException);
     }
     var responseBuilder = Response.CreateBuilder ();
     if (procedure.HasReturnType)
         responseBuilder.ReturnValue = EncodeReturnValue (procedure, returnValue);
     return responseBuilder;
 }
예제 #14
0
파일: Services.cs 프로젝트: 602p/krpc
 /// <summary>
 /// Decode the arguments for a request
 /// </summary>
 public object[] DecodeArguments(ProcedureSignature procedure, Request request)
 {
     return DecodeArguments (procedure, request.ArgumentsList);
 }
예제 #15
0
파일: Services.cs 프로젝트: 602p/krpc
 /// <summary>
 /// Executes the given request and returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response.Builder HandleRequest(ProcedureSignature procedure, Request request)
 {
     return HandleRequest (procedure, DecodeArguments (procedure, request.ArgumentsList));
 }
예제 #16
0
파일: Services.cs 프로젝트: BasConijn/krpc
 /// <summary>
 /// Executes the request, continuing using the give continuation. Returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response.Builder HandleRequest(ProcedureSignature procedure, IContinuation continuation)
 {
     object returnValue;
     try {
         returnValue = continuation.RunUntyped ();
     } catch (YieldException) {
         throw;
     } catch (Exception e) {
         throw new RPCException ("Procedure '" + procedure.FullyQualifiedName + "' threw an exception. " +
         e.GetType () + ": " + e.Message);
     }
     var responseBuilder = Response.CreateBuilder ();
     if (procedure.HasReturnType)
         responseBuilder.ReturnValue = EncodeReturnValue (procedure, returnValue);
     return responseBuilder;
 }
예제 #17
0
파일: Services.cs 프로젝트: 602p/krpc
        /// <summary>
        /// Encodes the value returned by a procedure handler into a ByteString
        /// </summary>
        ByteString EncodeReturnValue(ProcedureSignature procedure, object returnValue)
        {
            // Check the return value is missing
            if (returnValue == null && !TypeUtils.IsAClassType (procedure.ReturnType)) {
                throw new RPCException (
                    procedure,
                    procedure.FullyQualifiedName + " returned null. " +
                    "Expected an object of type " + procedure.ReturnType);
            }

            // Check if the return value is of a valid type
            if (!TypeUtils.IsAValidType (procedure.ReturnType)) {
                throw new RPCException (
                    procedure,
                    procedure.FullyQualifiedName + " returned an object of an invalid type. " +
                    "Expected " + procedure.ReturnType + "; got " + returnValue.GetType ());
            }

            // Encode it as a ByteString
            return Encode (procedure.ReturnType, returnValue);
        }
예제 #18
0
파일: Services.cs 프로젝트: 602p/krpc
        /// <summary>
        /// Decode the arguments for a procedure from a serialized request
        /// </summary>
        object[] DecodeArguments(ProcedureSignature procedure, IList<Schema.KRPC.Argument> arguments)
        {
            // Rearrange argument values
            var argumentValues = new ByteString [procedure.Parameters.Count];
            foreach (var argument in arguments)
                argumentValues [argument.Position] = argument.Value;

            var decodedArgumentValues = new object[procedure.Parameters.Count];
            for (int i = 0; i < procedure.Parameters.Count; i++) {
                var type = procedure.Parameters [i].Type;
                var value = argumentValues [i];
                if (value == null) {
                    // Handle default arguments
                    if (!procedure.Parameters [i].HasDefaultArgument)
                        throw new RPCException (procedure, "Argument not specified for parameter " + procedure.Parameters [i].Name + " in " + procedure.FullyQualifiedName + ". ");
                    decodedArgumentValues [i] = Type.Missing;
                } else {
                    // Decode argument
                    try {
                        decodedArgumentValues [i] = Decode (procedure, i, type, value);
                    } catch (Exception e) {
                        throw new RPCException (
                            procedure,
                            "Failed to decode argument for parameter " + procedure.Parameters [i].Name + " in " + procedure.FullyQualifiedName + ". " +
                            "Expected an argument of type " + TypeUtils.GetTypeName (type) + ". " +
                            e.GetType ().Name + ": " + e.Message);
                    }
                }
            }
            return decodedArgumentValues;
        }
예제 #19
0
파일: Services.cs 프로젝트: 602p/krpc
 /// <summary>
 /// Decode a serialized value
 /// </summary>
 object Decode(ProcedureSignature procedure, int i, Type type, ByteString value)
 {
     if (TypeUtils.IsAClassType (type)) {
         return ObjectStore.Instance.GetInstance ((ulong)ProtocolBuffers.ReadValue (value, typeof(ulong)));
     } else if (TypeUtils.IsACollectionType (type)) {
         return DecodeCollection (procedure, i, type, value);
     } else if (ProtocolBuffers.IsAMessageType (type)) {
         var builder = procedure.ParameterBuilders [i];
         builder.WeakMergeFrom (value);
         var built = builder.WeakBuild ();
         builder.WeakClear ();
         return built;
     } else if (ProtocolBuffers.IsAnEnumType (type) || TypeUtils.IsAnEnumType (type)) {
         // TODO: Assumes it's underlying type is int
         var enumValue = ProtocolBuffers.ReadValue (value, typeof(int));
         if (!Enum.IsDefined (type, enumValue))
             throw new RPCException (procedure, "Failed to convert value " + enumValue + " to enumeration type " + type);
         return Enum.ToObject (type, enumValue);
     } else {
         return ProtocolBuffers.ReadValue (value, type);
     }
 }
예제 #20
0
파일: Services.cs 프로젝트: 602p/krpc
 /// <summary>
 /// Executes the request, continuing using the given continuation. Returns a response builder with the relevant
 /// fields populated. Throws YieldException, containing a continuation, if the request yields.
 /// Throws RPCException if processing the request fails.
 /// </summary>
 public Response.Builder HandleRequest(ProcedureSignature procedure, IContinuation continuation)
 {
     object returnValue;
     try {
         returnValue = continuation.RunUntyped ();
     } catch (YieldException) {
         throw;
     } catch (Exception e) {
         throw new RPCException (procedure, e);
     }
     var responseBuilder = Response.CreateBuilder ();
     if (procedure.HasReturnType)
         responseBuilder.ReturnValue = EncodeReturnValue (procedure, returnValue);
     return responseBuilder;
 }
예제 #21
0
 void CheckDocumentation (ProcedureSignature proc)
 {
     CheckDocumentation (proc.FullyQualifiedName, proc.Documentation);
 }
예제 #22
0
파일: Services.cs 프로젝트: paperclip/krpc
 public Response HandleRequest (ProcedureSignature procedure, IContinuation continuation)
 {
     object returnValue;
     try {
         returnValue = continuation.RunUntyped ();
     } catch (YieldException) {
         throw;
     } catch (Exception e) {
         throw new RPCException (procedure, e);
     }
     var response = new Response ();
     if (procedure.HasReturnType) {
         CheckReturnValue (procedure, returnValue);
         response.ReturnValue = returnValue;
     }
     return response;
 }