Ejemplo n.º 1
0
        private void ProcessSync(ZkSession session, BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw)
        {
            var syncCat = "Sync";

            string serviceTypeName;

            if (_requireZk)
            {
                //use session and encryption - if throws should not have gotten this far
                var len   = binReader.ReadInt32();
                var bytes = binReader.ReadBytes(len);
                var data  = session.Crypto.Decrypt(bytes);
                serviceTypeName = data.ConverToString();
            }
            else
            {
                serviceTypeName = binReader.ReadString();
            }

            int serviceKey;

            if (_serviceKeys.TryGetValue(serviceTypeName, out serviceKey))
            {
                ServiceInstance instance;
                if (_services.TryGetValue(serviceKey, out instance))
                {
                    syncCat = instance.InterfaceType.Name;
                    //Create a list of sync infos from the dictionary
                    var syncBytes = _serializer.Serialize(instance.ServiceSyncInfo);
                    if (_requireZk)
                    {
                        _log.Debug("Unencrypted data sent to server: {0}", Convert.ToBase64String(syncBytes));
                        var encData = session.Crypto.Encrypt(syncBytes);
                        binWriter.Write(encData.Length);
                        binWriter.Write(encData);
                        _log.Debug("Encrypted data sent server: {0}", Convert.ToBase64String(encData));
                    }
                    else
                    {
                        binWriter.Write(syncBytes.Length);
                        binWriter.Write(syncBytes);
                    }
                }
            }
            else
            {
                //return zero to indicate type or version of type not found
                binWriter.Write(0);
            }
            binWriter.Flush();
            _log.Debug("SyncInterface for {0} in {1}ms.", syncCat, sw.ElapsedMilliseconds);
        }
Ejemplo n.º 2
0
        private void ProcessInvocation(ZkSession session, BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw)
        {
            //read service instance key
            var             cat  = "unknown";
            var             stat = "MethodInvocation";
            int             invokedServiceKey = binReader.ReadInt32();
            ServiceInstance invokedInstance;

            if (_services.TryGetValue(invokedServiceKey, out invokedInstance))
            {
                cat = invokedInstance.InterfaceType.Name;
                //read the method identifier
                int methodHashCode = binReader.ReadInt32();
                if (invokedInstance.InterfaceMethods.ContainsKey(methodHashCode))
                {
                    MethodInfo method;
                    invokedInstance.InterfaceMethods.TryGetValue(methodHashCode, out method);
                    stat = method.Name;

                    bool[] isByRef;
                    invokedInstance.MethodParametersByRef.TryGetValue(methodHashCode, out isByRef);

                    //read parameter data
                    object[] parameters;
                    if (_requireZk)
                    {
                        var len     = binReader.ReadInt32();
                        var encData = binReader.ReadBytes(len);
                        _log.Debug("Encrypted data received from server: {0}", Convert.ToBase64String(encData));
                        var data = session.Crypto.Decrypt(encData);
                        _log.Debug("Decrypted data received from server: {0}", Convert.ToBase64String(data));
                        using (var ms = new MemoryStream(data))
                            using (var br = new BinaryReader(ms))
                            {
                                parameters = _parameterTransferHelper.ReceiveParameters(br);
                            }
                    }
                    else
                    {
                        parameters = _parameterTransferHelper.ReceiveParameters(binReader);
                    }

                    //invoke the method
                    object[] returnParameters;
                    var      returnMessageType = MessageType.ReturnValues;
                    try
                    {
                        object returnValue = method.Invoke(invokedInstance.SingletonInstance, parameters);
                        if (returnValue is Task task)
                        {
                            task.GetAwaiter().GetResult();
                            var prop = task.GetType().GetProperty("Result");
                            returnValue = prop?.GetValue(task);
                        }
                        //the result to the client is the return value (null if void) and the input parameters
                        returnParameters    = new object[1 + parameters.Length];
                        returnParameters[0] = returnValue;
                        for (int i = 0; i < parameters.Length; i++)
                        {
                            returnParameters[i + 1] = isByRef[i] ? parameters[i] : null;
                        }
                    }
                    catch (Exception ex)
                    {
                        //an exception was caught. Rethrow it client side
                        returnParameters  = new object[] { ex };
                        returnMessageType = MessageType.ThrowException;
                    }

                    //send the result back to the client
                    // (1) write the message type
                    binWriter.Write((int)returnMessageType);

                    // (2) write the return parameters
                    if (_requireZk)
                    {
                        byte[] data;
                        using (var ms = new MemoryStream())
                            using (var bw = new BinaryWriter(ms))
                            {
                                _parameterTransferHelper.SendParameters(
                                    invokedInstance.ServiceSyncInfo.UseCompression,
                                    invokedInstance.ServiceSyncInfo.CompressionThreshold,
                                    bw,
                                    returnParameters);
                                data = ms.ToArray();
                            }
                        _log.Debug("Unencrypted data sent server: {0}", Convert.ToBase64String(data));
                        var encData = session.Crypto.Encrypt(data);
                        _log.Debug("Encrypted data sent server: {0}", Convert.ToBase64String(encData));
                        binWriter.Write(encData.Length);
                        binWriter.Write(encData);
                    }
                    else
                    {
                        _parameterTransferHelper.SendParameters(
                            invokedInstance.ServiceSyncInfo.UseCompression,
                            invokedInstance.ServiceSyncInfo.CompressionThreshold,
                            binWriter,
                            returnParameters);
                    }
                }
                else
                {
                    binWriter.Write((int)MessageType.UnknownMethod);
                }
            }
            else
            {
                binWriter.Write((int)MessageType.UnknownMethod);
            }

            //flush
            binWriter.Flush();
            _stats.Log(cat, stat, sw.ElapsedMilliseconds);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// This method handles all requests from a single client.
        /// There is one thread running this method for each connected client.
        /// </summary>
        /// <param name="readStream">The read/write stream.</param>
        /// <param name="writeStream">The read/write stream.</param>
        protected virtual void ProcessRequest(Stream readStream, Stream writeStream)
        {
            if (null == readStream || null == writeStream)
            {
                return;
            }

            var  binReader  = new BinaryReader(readStream);
            var  binWriter  = new BinaryWriter(writeStream);
            bool doContinue = true;

            try
            {
                ZkSession zkSession = null;
                do
                {
                    var sw = Stopwatch.StartNew();
                    try
                    {
                        //read message type
                        var messageType = (MessageType)binReader.ReadInt32();
                        switch (messageType)
                        {
                        case MessageType.ZkInitiate:
                            zkSession  = new ZkSession(_zkRepository, _log, _stats);
                            doContinue = zkSession.ProcessZkInitiation(binReader, binWriter, sw);
                            break;

                        case MessageType.ZkProof:
                            if (null == zkSession)
                            {
                                throw new NullReferenceException("session null");
                            }
                            doContinue = zkSession.ProcessZkProof(binReader, binWriter, sw);
                            break;

                        case MessageType.SyncInterface:
                            ProcessSync(zkSession, binReader, binWriter, sw);
                            break;

                        case MessageType.MethodInvocation:
                            ProcessInvocation(zkSession, binReader, binWriter, sw);
                            break;

                        case MessageType.TerminateConnection:
                            doContinue = false;
                            break;

                        default:
                            doContinue = false;
                            break;
                        }
                    }
                    catch (Exception e) //do not resume operation on this thread if any errors are unhandled.
                    {
                        _log.Error("Error in ProcessRequest: {0}", e.ToString().Flatten());
                        doContinue = false;
                    }
                    sw.Stop();
                }while (doContinue);
            }
            catch (Exception fatalException)
            {
                _log.Fatal("Fatal error in ProcessRequest: {0}", fatalException.ToString().Flatten());
            }
            finally
            {
                binReader.Close();
                binWriter.Close();
            }
        }