private async Task readMessageAsync(string endpoint, Stream stream,
                                            Func <Message[], IMessageAcceptance> acceptMessages)
        {
            bool serializationErrorOccurred = false;

            Message[] messages = null;
            try
            {
                var length = await new ReadLength(Logger, endpoint).GetAsync(stream).ConfigureAwait(false);
                messages = await new ReadMessage(Logger, length, endpoint).GetAsync(stream).ConfigureAwait(false);
            }
            catch (SerializationException exception)
            {
                Logger.Info("Unable to deserialize messages", exception);
                serializationErrorOccurred = true;
            }

            if (serializationErrorOccurred)
            {
                await new WriteSerializationError(Logger).ProcessAsync(stream).ConfigureAwait(false);
            }

            IMessageAcceptance acceptance = null;

            byte[] errorBytes = null;
            try
            {
                acceptance = acceptMessages(messages);
                Logger.Debug("All messages from {0} were accepted", endpoint);
            }
            catch (QueueDoesNotExistsException)
            {
                Logger.Info("Failed to accept messages from {0} because queue does not exists", endpoint);
                errorBytes = ProtocolConstants.QueueDoesNoExiststBuffer;
            }
            catch (Exception exception)
            {
                errorBytes = ProtocolConstants.ProcessingFailureBuffer;
                Logger.Info("Failed to accept messages from " + endpoint, exception);
            }

            if (errorBytes != null)
            {
                await new WriteProcessingError(Logger, errorBytes, endpoint).ProcessAsync(stream).ConfigureAwait(false);
                return;
            }

            try
            {
                await new WriteReceived(Logger, endpoint).ProcessAsync(stream).ConfigureAwait(false);
            }
            catch (Exception)
            {
                acceptance.Abort();
                return;
            }

            try
            {
                await new ReadAcknowledgement(Logger, endpoint).ProcessAsync(stream).ConfigureAwait(false);
            }
            catch (Exception)
            {
                acceptance.Abort();
                return;
            }

            bool commitSuccessful;

            try
            {
                acceptance.Commit();
                commitSuccessful = true;
            }
            catch (Exception exception)
            {
                Logger.Info("Unable to commit messages from " + endpoint, exception);
                commitSuccessful = false;
            }

            if (commitSuccessful == false)
            {
                await new WriteRevert(Logger, endpoint).ProcessAsync(stream).ConfigureAwait(false);
            }
        }
Example #2
0
        private IEnumerator <int> ProcessRequest(TcpClient client, AsyncEnumerator ae)
        {
            try
            {
                using (client)
                    using (var stream = client.GetStream())
                    {
                        var sender = client.Client.RemoteEndPoint;

                        var lenOfDataToReadBuffer = new byte[sizeof(int)];

                        var lenEnumerator = new AsyncEnumerator(ae.ToString());
                        try
                        {
                            lenEnumerator.BeginExecute(
                                StreamUtil.ReadBytes(lenOfDataToReadBuffer, stream, lenEnumerator, "length data", false), ae.End());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Unable to read length data from " + sender, exception);
                            yield break;
                        }

                        yield return(1);

                        try
                        {
                            lenEnumerator.EndExecute(ae.DequeueAsyncResult());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Unable to read length data from " + sender, exception);
                            yield break;
                        }

                        var lengthOfDataToRead = BitConverter.ToInt32(lenOfDataToReadBuffer, 0);
                        if (lengthOfDataToRead < 0)
                        {
                            logger.WarnFormat("Got invalid length {0} from sender {1}", lengthOfDataToRead, sender);
                            yield break;
                        }
                        logger.DebugFormat("Reading {0} bytes from {1}", lengthOfDataToRead, sender);

                        var buffer = new byte[lengthOfDataToRead];

                        var readBufferEnumerator = new AsyncEnumerator(ae.ToString());
                        try
                        {
                            readBufferEnumerator.BeginExecute(
                                StreamUtil.ReadBytes(buffer, stream, readBufferEnumerator, "message data", false), ae.End());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Unable to read message data from " + sender, exception);
                            yield break;
                        }
                        yield return(1);

                        try
                        {
                            readBufferEnumerator.EndExecute(ae.DequeueAsyncResult());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Unable to read message data from " + sender, exception);
                            yield break;
                        }

                        Message[] messages = null;
                        try
                        {
                            messages = SerializationExtensions.ToMessages(buffer);
                            logger.DebugFormat("Deserialized {0} messages from {1}", messages.Length, sender);
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Failed to deserialize messages from " + sender, exception);
                        }

                        if (messages == null)
                        {
                            try
                            {
                                stream.BeginWrite(ProtocolConstants.SerializationFailureBuffer, 0,
                                                  ProtocolConstants.SerializationFailureBuffer.Length, ae.End(), null);
                            }
                            catch (Exception exception)
                            {
                                logger.Warn("Unable to send serialization format error to " + sender, exception);
                                yield break;
                            }
                            yield return(1);

                            try
                            {
                                stream.EndWrite(ae.DequeueAsyncResult());
                            }
                            catch (Exception exception)
                            {
                                logger.Warn("Unable to send serialization format error to " + sender, exception);
                            }

                            yield break;
                        }

                        IMessageAcceptance acceptance = null;
                        byte[]             errorBytes = null;
                        try
                        {
                            acceptance = acceptMessages(messages);
                            logger.DebugFormat("All messages from {0} were accepted", sender);
                        }
                        catch (QueueDoesNotExistsException)
                        {
                            logger.WarnFormat("Failed to accept messages from {0} because queue does not exists", sender);
                            errorBytes = ProtocolConstants.QueueDoesNoExiststBuffer;
                        }
                        catch (Exception exception)
                        {
                            errorBytes = ProtocolConstants.ProcessingFailureBuffer;
                            logger.Warn("Failed to accept messages from " + sender, exception);
                        }

                        if (errorBytes != null)
                        {
                            try
                            {
                                stream.BeginWrite(errorBytes, 0,
                                                  errorBytes.Length, ae.End(), null);
                            }
                            catch (Exception exception)
                            {
                                logger.Warn("Unable to send processing failure from " + sender, exception);
                                yield break;
                            }
                            yield return(1);

                            try
                            {
                                stream.EndWrite(ae.DequeueAsyncResult());
                            }
                            catch (Exception exception)
                            {
                                logger.Warn("Unable to send processing failure from " + sender, exception);
                            }
                            yield break;
                        }

                        logger.DebugFormat("Sending reciept notice to {0}", sender);
                        try
                        {
                            stream.BeginWrite(ProtocolConstants.RecievedBuffer, 0, ProtocolConstants.RecievedBuffer.Length,
                                              ae.End(), null);
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Could not send reciept notice to " + sender, exception);
                            acceptance.Abort();
                            yield break;
                        }
                        yield return(1);

                        try
                        {
                            stream.EndWrite(ae.DequeueAsyncResult());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Could not send reciept notice to " + sender, exception);
                            acceptance.Abort();
                            yield break;
                        }

                        logger.DebugFormat("Reading acknowledgement about accepting messages to {0}", sender);

                        var acknowledgementBuffer = new byte[ProtocolConstants.AcknowledgedBuffer.Length];

                        var readAcknoweldgement = new AsyncEnumerator(ae.ToString());
                        try
                        {
                            readAcknoweldgement.BeginExecute(
                                StreamUtil.ReadBytes(acknowledgementBuffer, stream, readAcknoweldgement, "acknowledgement", false),
                                ae.End());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Error reading acknowledgement from " + sender, exception);
                            acceptance.Abort();
                            yield break;
                        }
                        yield return(1);

                        try
                        {
                            readAcknoweldgement.EndExecute(ae.DequeueAsyncResult());
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Error reading acknowledgement from " + sender, exception);
                            acceptance.Abort();
                            yield break;
                        }

                        var senderResponse = Encoding.Unicode.GetString(acknowledgementBuffer);
                        if (senderResponse != ProtocolConstants.Acknowledged)
                        {
                            logger.WarnFormat("Sender did not respond with proper acknowledgement, the reply was {0}",
                                              senderResponse);
                            acceptance.Abort();
                        }

                        bool commitSuccessful;
                        try
                        {
                            acceptance.Commit();
                            commitSuccessful = true;
                        }
                        catch (Exception exception)
                        {
                            logger.Warn("Unable to commit messages from " + sender, exception);
                            commitSuccessful = false;
                        }

                        if (commitSuccessful == false)
                        {
                            bool writeSuccessful;
                            try
                            {
                                stream.BeginWrite(ProtocolConstants.RevertBuffer, 0, ProtocolConstants.RevertBuffer.Length,
                                                  ae.End(),
                                                  null);
                                writeSuccessful = true;
                            }
                            catch (Exception e)
                            {
                                logger.Warn("Unable to send revert message to " + sender, e);
                                writeSuccessful = false;
                            }

                            if (writeSuccessful)
                            {
                                yield return(1);


                                try
                                {
                                    stream.EndWrite(ae.DequeueAsyncResult());
                                }
                                catch (Exception exception)
                                {
                                    logger.Warn("Unable to send revert message to " + sender, exception);
                                }
                            }
                        }
                    }
            }
            finally
            {
                var copy = CompletedRecievingMessages;
                if (copy != null)
                {
                    copy();
                }
            }
        }