/// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IRemoteSender.Send(System.String)"]/*'/>
        public void Send(string message)
        {
            metricsUtilities.Begin(new MessageSendTime());

            try
            {
                CheckNotDisposed();
                CheckConnectionOpen();

                // Send a message
                ITextMessage textMessage = session.CreateTextMessage(message);
                textMessage.Properties.SetString(filterIdentifier, messageFilter);
                try
                {
                    producer.Send(textMessage);
                }
                catch (Exception e)
                {
                    throw new Exception("Error sending message.", e);
                }
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new MessageSendTime());
                throw;
            }

            metricsUtilities.End(new MessageSendTime());
            metricsUtilities.Increment(new MessageSent());
            loggingUtilities.Log(this, LogLevel.Information, "Message sent.");
        }
Пример #2
0
        /// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IRemoteReceiver.Receive"]/*'/>
        public string Receive()
        {
            CheckNotDisposed();
            string returnMessage = "";

            cancelRequest = false;

            try
            {
                while (cancelRequest == false)
                {
                    if (fileSystem.CheckFileExists(messageFilePath) == true)
                    {
                        if (fileSystem.CheckFileExists(lockFilePath) == false)
                        {
                            metricsUtilities.Begin(new MessageReceiveTime());

                            try
                            {
                                returnMessage = messageFile.ReadAll();
                                fileSystem.DeleteFile(messageFilePath);
                            }
                            catch (Exception e)
                            {
                                metricsUtilities.CancelBegin(new MessageReceiveTime());
                                throw;
                            }

                            metricsUtilities.End(new MessageReceiveTime());
                            metricsUtilities.Increment(new MessageReceived());
                            metricsUtilities.Add(new ReceivedMessageSize(returnMessage.Length));
                            loggingUtilities.LogMessageReceived(this, returnMessage);
                            break;
                        }
                    }
                    else
                    {
                        waitingForTimeout = true;
                        if (readLoopTimeout > 0)
                        {
                            System.Threading.Thread.Sleep(readLoopTimeout);
                        }
                        waitingForTimeout = false;
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("Error receiving message.", e);
            }

            return(returnMessage);
        }
        /// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IMethodInvocationRemoteReceiver.Receive"]/*'/>
        public void Receive()
        {
            cancelRequest = false;

            receiveLoopThread = new Thread(delegate()
            {
                while (cancelRequest == false)
                {
                    try
                    {
                        string serializedMethodInvocation = receiver.Receive();
                        if (serializedMethodInvocation != "")
                        {
                            metricsUtilities.Begin(new RemoteMethodReceiveTime());

                            IMethodInvocation receivedMethodInvocation;

                            try
                            {
                                receivedMethodInvocation = serializer.Deserialize(serializedMethodInvocation);
                                OnMethodInvocationReceived(new MethodInvocationReceivedEventArgs(receivedMethodInvocation));
                            }
                            catch (Exception e)
                            {
                                metricsUtilities.CancelBegin(new RemoteMethodReceiveTime());
                                throw;
                            }

                            loggingUtilities.Log(this, LogLevel.Information, "Received method invocation '" + receivedMethodInvocation.Name + "'.");
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Failed to invoke method.", e);
                    }
                }
            });
            receiveLoopThread.Name = "MethodInvocationRemoting.MethodInvocationRemoteReceiver message receive worker thread.";
            receiveLoopThread.Start();
        }
Пример #4
0
        /// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IMethodInvocationSerializer.Serialize(MethodInvocationRemoting.IMethodInvocation)"]/*'/>
        public string Serialize(IMethodInvocation inputMethodInvocation)
        {
            metricsUtilities.Begin(new MethodInvocationSerializeTime());

            string returnString = "";

            try
            {
                returnString = SerializeObject(inputMethodInvocation);
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new MethodInvocationSerializeTime());
                throw new SerializationException("Failed to serialize method invocation '" + inputMethodInvocation.Name + "'.", inputMethodInvocation, e);
            }

            metricsUtilities.End(new MethodInvocationSerializeTime());
            metricsUtilities.Increment(new MethodInvocationSerialized());
            metricsUtilities.Add(new SerializedMethodInvocationSize(returnString.Length));
            loggingUtilities.LogSerializedItem(this, returnString, "method invocation");

            return(returnString);
        }
        /// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IMethodInvocationRemoteSender.InvokeMethod(MethodInvocationRemoting.IMethodInvocation)"]/*'/>
        public object InvokeMethod(IMethodInvocation inputMethodInvocation)
        {
            metricsUtilities.Begin(new RemoteMethodSendTime());

            object returnValue;

            try
            {
                // Check that inputted method invocation does not have a void return type.
                if (inputMethodInvocation.ReturnType == null)
                {
                    throw new ArgumentException("Method invocation cannot have a void return type.", "inputMethodInvocation");
                }

                string serializedReturnValue = SerializeAndSend(inputMethodInvocation);
                try
                {
                    returnValue = serializer.DeserializeReturnValue(serializedReturnValue);
                }
                catch (Exception e)
                {
                    throw new Exception("Failed to deserialize return value.", e);
                }
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new RemoteMethodSendTime());
                throw;
            }

            metricsUtilities.End(new RemoteMethodSendTime());
            metricsUtilities.Increment(new RemoteMethodSent());
            loggingUtilities.Log(this, LogLevel.Information, "Invoked method '" + inputMethodInvocation.Name + "'.");

            return(returnValue);
        }
        /// <include file='InterfaceDocumentationComments.xml' path='doc/members/member[@name="M:MethodInvocationRemoting.IRemoteSender.Send(System.String)"]/*'/>
        public void Send(string message)
        {
            metricsUtilities.Begin(new MessageSendTime());

            CheckNotDisposed();

            try
            {
                // Lock file is created before data is written to the message file
                //   The FileRemoteReceiver class checks for the absence of the lock file to prevent attempting to open the message file when it is partially written and causing an exception
                lockFile.WriteAll("");
                messageFile.WriteAll(message);
                fileSystem.DeleteFile(lockFilePath);
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new MessageSendTime());
                throw new Exception("Error sending message.", e);
            }

            metricsUtilities.End(new MessageSendTime());
            metricsUtilities.Increment(new MessageSent());
            loggingUtilities.Log(this, LogLevel.Information, "Message sent.");
        }
        //------------------------------------------------------------------------------
        //
        // Method: HandleExceptionAndResend
        //
        //------------------------------------------------------------------------------
        /// <summary>
        /// Handles an exception that occurred when attempting to send a message, before reconnecting and re-sending.
        /// </summary>
        /// <param name="sendException">The exception that occurred when attempting to send the message.</param>
        /// <param name="message">The message to send.</param>
        private void HandleExceptionAndResend(Exception sendException, string message)
        {
            /*
             * In testing of this class, the only exhibited exception for probable real-world network issues (i.e. disconnecting network cable), was the System.IO.IOException.
             * However, the documentation states that numerous exceptions can potentially be thrown by the NetworkStream and TcpClient classes.  Hence the below code block handles all theoretically potential exceptions.
             * These exceptions, and the classes which can cause them are listed below...
             * TcpClient.Available
             *   ObjectDisposedException
             *   SocketException
             * TcpClient.GetStream()
             *   InvalidOperationException
             *   ObjectDisposedException
             * NetworkStream.ReadByte()
             *   IOException
             *   ObjectDisposedException
             * NetworkStream.Write(byte[] buffer, int offset, int size)
             *   IOException
             *   ObjectDisposedException
             */
            try
            {
                if (sendException is System.IO.IOException)
                {
                    logger.Log(this, LogLevel.Error, sendException.GetType().Name + " occurred whilst attempting to send message.", sendException);

                    // If the TCP client is still connected, the situation cannot be handled so re-throw the exception
                    if (client.Connected == true)
                    {
                        throw new Exception("Error sending message.  IOException occurred when sending message, but client is reporting that it is still connected.", sendException);
                    }

                    logger.Log(this, LogLevel.Warning, "Disconnected from TCP socket.");
                }
                else if ((sendException is MessageAcknowledgementTimeoutException) ||
                         (sendException is System.Net.Sockets.SocketException) ||
                         (sendException is ObjectDisposedException) ||
                         (sendException is InvalidOperationException))
                {
                    logger.Log(this, LogLevel.Error, sendException.GetType().Name + " occurred whilst attempting to send message.", sendException);
                }
                else
                {
                    throw new Exception("Error sending message.  Unhandled exception while sending message.", sendException);
                }

                logger.Log(this, LogLevel.Warning, "Attempting to reconnect to TCP socket.");

                client.Close();
                AttemptConnect();
                metricsUtilities.Increment(new TcpRemoteSenderReconnected());
                try
                {
                    EncodeAndSend(message);
                }
                catch (Exception e)
                {
                    throw new Exception("Error sending message.  Failed to send message after reconnecting.", e);
                }
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new MessageSendTime());
                throw;
            }
        }
        //------------------------------------------------------------------------------
        //
        // Method: HandleExceptionAndRereadMessage
        //
        //------------------------------------------------------------------------------
        /// <summary>
        /// Handles an exception that occurred when attempting to read a message, before re-establishing the connection and repeating the read operation.
        /// </summary>
        /// <param name="readException">The exception that occurred when attempting to read the message.</param>
        /// <param name="parseState">The current state of parsing the message.</param>
        /// <param name="messageSequenceNumber">Populated with the seqence number of the received message.</param>
        /// <returns>The bytes of the message that were read.</returns>
        private Queue <byte> HandleExceptionAndRereadMessage(Exception readException, ref MessageParseState parseState, ref int messageSequenceNumber)
        {
            /*
             * In testing of this class, the only exhibited exception for probable real-world network issues (i.e. disconnecting network cable), was the System.IO.IOException.
             * However, the documentation states that numerous exceptions can potentially be thrown by the NetworkStream and TcpClient classes.  Hence the below code block handles all theoretically potential exceptions.
             * These exceptions, and the methods which can cause them are listed below...
             * TcpClient.Available
             *   ObjectDisposedException
             *   SocketException
             * TcpClient.GetStream()
             *   InvalidOperationException
             *   ObjectDisposedException
             * NetworkStream.Read(byte[] buffer, int offset, int size)
             *   IOException
             *   ObjectDisposedException
             * NetworkStream.WriteByte()
             *   IOException
             *   NotSupportedException
             *   ObjectDisposedException
             */
            Queue <byte> messageBytes = new Queue <byte>();

            try
            {
                if (readException is System.IO.IOException)
                {
                    logger.Log(this, LogLevel.Error, "IOException occurred whilst attempting to receive and acknowledge message.", readException);
                }
                else if ((readException is System.Net.Sockets.SocketException) ||
                         (readException is ObjectDisposedException) ||
                         (readException is InvalidOperationException) ||
                         (readException is NotSupportedException))
                {
                    logger.Log(this, LogLevel.Error, readException.GetType().Name + " occurred whilst attempting to receive and acknowledge message.", readException);
                }
                else
                {
                    throw new Exception("Error receiving message.  Unhandled exception while attempting to receive and acknowledge message.", readException);
                }

                logger.Log(this, LogLevel.Warning, "Attempting to reconnect to and re-receive.");

                AttemptConnect();
                metricsUtilities.Increment(new TcpRemoteReceiverReconnected());
                parseState = MessageParseState.StartOfMessage;
                try
                {
                    messageBytes = SetupAndReadMessage(ref parseState, ref messageSequenceNumber);
                }
                catch (Exception e)
                {
                    throw new Exception("Error receiving message.  Failed to read message after reconnecting.", e);
                }
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new MessageReceiveTime());
                throw;
            }

            return(messageBytes);
        }
Пример #9
0
        //------------------------------------------------------------------------------
        //
        // Method: DecompressString
        //
        //------------------------------------------------------------------------------
        /// <summary>
        /// Decompresses a string.
        /// </summary>
        /// <param name="inputString">The string to decompress.</param>
        /// <returns>The decompressed string.</returns>
        private string DecompressString(string inputString)
        {
            metricsUtilities.Begin(new StringDecompressTime());

            decompressing = true;

            List <byte[]> readBuffers = new List <byte[]>();
            int           currentReadBufferPosition = 0;
            string        returnString = "";

            try
            {
                // Decode from base 64
                byte[] encodedBytes = Convert.FromBase64String(inputString);
                using (MemoryStream decompressedStringStream = new MemoryStream(encodedBytes))
                    using (GZipStream decompressor = new GZipStream(decompressedStringStream, CompressionMode.Decompress))
                    {
                        int bytesRead = -1;
                        while (bytesRead != 0)
                        {
                            // If the list of buffers is empty, or the read position in the current (last) buffer is at the end of the buffer, then create a new read buffer
                            if ((readBuffers.Count == 0) || (currentReadBufferPosition == decompressionBufferSize))
                            {
                                readBuffers.Add(new byte[decompressionBufferSize]);
                                currentReadBufferPosition = 0;

                                metricsUtilities.Increment(new RemoteReceiverDecompressorReadBufferCreated());
                            }
                            bytesRead = decompressor.Read(readBuffers[readBuffers.Count - 1], currentReadBufferPosition, decompressionBufferSize - currentReadBufferPosition);
                            currentReadBufferPosition = currentReadBufferPosition + bytesRead;
                        }
                        decompressor.Close();
                        decompressedStringStream.Close();
                    }

                // Create decompressed byte array with size as buffer size times the number of buffers (except the last buffer), plus the position within the last buffer
                byte[] decompressedBytes = new byte[((readBuffers.Count - 1) * decompressionBufferSize) + currentReadBufferPosition];
                // Copy the contents of the read buffers into the decompressed byte array
                int decompressedBytesPosition = 0;
                foreach (byte[] currentReadBuffer in readBuffers)
                {
                    if (currentReadBuffer != readBuffers[readBuffers.Count - 1])
                    {
                        Array.Copy(currentReadBuffer, 0, decompressedBytes, decompressedBytesPosition, decompressionBufferSize);
                        decompressedBytesPosition = decompressedBytesPosition + decompressionBufferSize;
                    }
                    else
                    {
                        Array.Copy(currentReadBuffer, 0, decompressedBytes, decompressedBytesPosition, currentReadBufferPosition);
                    }
                }

                returnString = stringEncoding.GetString(decompressedBytes);
            }
            catch (Exception e)
            {
                metricsUtilities.CancelBegin(new StringDecompressTime());
                throw new Exception("Error decompressing message.", e);
            }

            metricsUtilities.End(new StringDecompressTime());
            metricsUtilities.Increment(new StringDecompressed());
            loggingUtilities.LogDecompressedString(this, returnString);

            decompressing = false;
            return(returnString);
        }