private IEnumerator <int> SendInternal(AsyncEnumerator ae) { try { using (var client = new TcpClient()) { try { client.BeginConnect(Destination.Host, Destination.Port, ae.End(), null); } catch (Exception exception) { logger.WarnFormat("Failed to connect to {0} because {1}", Destination, exception); Failure(exception); yield break; } yield return(1); try { client.EndConnect(ae.DequeueAsyncResult()); } catch (Exception exception) { logger.WarnFormat("Failed to connect to {0} because {1}", Destination, exception); Failure(exception); yield break; } logger.DebugFormat("Successfully connected to {0}", Destination); using (var stream = client.GetStream()) { var buffer = Messages.Serialize(); var bufferLenInBytes = BitConverter.GetBytes(buffer.Length); logger.DebugFormat("Writing length of {0} bytes to {1}", buffer.Length, Destination); try { stream.BeginWrite(bufferLenInBytes, 0, bufferLenInBytes.Length, ae.End(), null); } catch (Exception exception) { logger.WarnFormat("Could not write to {0} because {1}", Destination, exception); Failure(exception); yield break; } yield return(1); try { stream.EndWrite(ae.DequeueAsyncResult()); } catch (Exception exception) { logger.WarnFormat("Could not write to {0} because {1}", Destination, exception); Failure(exception); yield break; } logger.DebugFormat("Writing {0} bytes to {1}", buffer.Length, Destination); try { stream.BeginWrite(buffer, 0, buffer.Length, ae.End(), null); } catch (Exception exception) { logger.WarnFormat("Could not write to {0} because {1}", Destination, exception); Failure(exception); yield break; } yield return(1); try { stream.EndWrite(ae.DequeueAsyncResult()); } catch (Exception exception) { logger.WarnFormat("Could not write to {0} because {1}", Destination, exception); Failure(exception); yield break; } logger.DebugFormat("Successfully wrote to {0}", Destination); var recieveBuffer = new byte[ProtocolConstants.RecievedBuffer.Length]; var readConfirmationEnumerator = new AsyncEnumerator(); try { readConfirmationEnumerator.BeginExecute( StreamUtil.ReadBytes(recieveBuffer, stream, readConfirmationEnumerator, "recieve confirmation", false), ae.End()); } catch (Exception exception) { logger.WarnFormat("Could not read confirmation from {0} because {1}", Destination, exception); Failure(exception); yield break; } yield return(1); try { readConfirmationEnumerator.EndExecute(ae.DequeueAsyncResult()); } catch (Exception exception) { logger.WarnFormat("Could not read confirmation from {0} because {1}", Destination, exception); Failure(exception); yield break; } var recieveRespone = Encoding.Unicode.GetString(recieveBuffer); if (recieveRespone == ProtocolConstants.QueueDoesNotExists) { logger.WarnFormat( "Response from reciever {0} is that queue does not exists", Destination); Failure(new QueueDoesNotExistsException()); yield break; } else if (recieveRespone != ProtocolConstants.Recieved) { logger.WarnFormat( "Response from reciever {0} is not the expected one, unexpected response was: {1}", Destination, recieveRespone); Failure(null); yield break; } try { stream.BeginWrite(ProtocolConstants.AcknowledgedBuffer, 0, ProtocolConstants.AcknowledgedBuffer.Length, ae.End(), null); } catch (Exception exception) { logger.WarnFormat("Failed to write acknowledgement to reciever {0} because {1}", Destination, exception); Failure(exception); yield break; } yield return(1); try { stream.EndWrite(ae.DequeueAsyncResult()); } catch (Exception exception) { logger.WarnFormat("Failed to write acknowledgement to reciever {0} because {1}", Destination, exception); Failure(exception); yield break; } var bookmarks = Success(); buffer = new byte[ProtocolConstants.RevertBuffer.Length]; var readRevertMessage = new AsyncEnumerator(ae.ToString()); bool startingToReadFailed = false; try { readRevertMessage.BeginExecute( StreamUtil.ReadBytes(buffer, stream, readRevertMessage, "revert", true), ae.End()); } catch (Exception) { //more or less expected startingToReadFailed = true; } if (startingToReadFailed) { yield break; } yield return(1); try { readRevertMessage.EndExecute(ae.DequeueAsyncResult()); var revert = Encoding.Unicode.GetString(buffer); if (revert == ProtocolConstants.Revert) { logger.Warn("Got back revert message from receiver, reverting send"); Revert(bookmarks); } } catch (Exception) { // expected, there is nothing to do here, the // reciever didn't report anything for us } } } } finally { var completed = SendCompleted; if (completed != null) { completed(); } } }
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(); } } }