/// <summary> /// Receives a message over a specified Duplex Channel Connection. /// </summary> /// <param name="connection">Duplex Channel Connection</param> /// <param name="ar">Result (for Async pattern)</param> /// <returns>Received message</returns> public static Message EndReceive(out Connection connection, IAsyncResult ar) { AsyncResult myAr = (AsyncResult)ar; connection = myAr.Connection; try { connection.LockRead(); if (connection.Socket == null) { throw new MessageException("Connection closed.", null, connection); } SocketError socketError; int bytesRead = connection.Socket.EndReceive(myAr.InternalAsyncResult, out socketError); if (bytesRead == 0 || connection.Channel == null) { throw new MessageException("Connection closed.", new SocketException((int)socketError), connection); } // read message identifier var reader = connection.Reader; if (bytesRead < SizeOfGuid) { var rest = reader.Read(myAr.Buffer, bytesRead, SizeOfGuid - bytesRead); if (rest < SizeOfGuid - bytesRead) { throw new MessageException("Insufficient data received. Got " + bytesRead + " bytes.", new SocketException((int)socketError), connection); } } // read message header Message retVal = new Message(); retVal.Guid = new Guid(myAr.Buffer); int headerLength = reader.ReadInt32(); MemoryStream headerStream = new MemoryStream(reader.ReadBytes(headerLength)); if (headerStream.Length != headerLength) { throw new Exception("Not enough headers read..."); } retVal.Headers = TransportHeaderWrapper.Deserialize(headerStream); int bodyLength = reader.ReadInt32(); if (bodyLength > 0) { retVal.messageBodyBytes = reader.ReadBytes(bodyLength); if (retVal.messageBodyBytes.Length != bodyLength) { throw new Exception("Not enough body read..."); } System.Diagnostics.Debug.Assert(retVal.MessageBody.CanRead); } Message.BeginReceive(connection, myAr.Callback, myAr.AsyncState); return(retVal); } catch (Exception e) { throw new MessageException("Error receiving message", e, connection); } finally { connection.ReleaseRead(); } }
/// <summary> /// Sends a specified message over a specified connection. /// </summary> /// <param name="connection">Duplex Channel Connection</param> /// <param name="guid">Unique identifier of the Message</param> /// <param name="headers">Remoting transport headers</param> /// <param name="message">Stream with raw data of the message</param> public static void Send(Connection connection, Guid guid, ITransportHeaders headers, Stream message) { try { connection.LockWrite(); BinaryWriter writer = connection.Writer; if (writer == null) { // Unexpected connection loss. Connection isn´t working anymore, so close it. connection.ReleaseWrite(); connection.Close(); connection = null; } else { writer.Write(guid.ToByteArray()); var headerStream = TransportHeaderWrapper.Serialize(headers); writer.Write((int)headerStream.Length); writer.Write(headerStream.GetBuffer(), 0, (int)headerStream.Length); writer.Write((int)message.Length); MemoryStream ms = message as MemoryStream; if (ms == null) { byte[] msgBuffer = new byte[message.Length]; message.Read(msgBuffer, 0, (int)message.Length); writer.Write(msgBuffer, 0, (int)message.Length); } else { writer.Write(ms.GetBuffer(), 0, (int)message.Length); } writer.Flush(); } } catch (ObjectDisposedException) { // Socket may be closed meanwhile. Connection isn't working anymore, so close it. connection.ReleaseWrite(); connection.Close(); connection = null; } catch (IOException) { // Unexpected connection loss. Connection isn't working anymore, so close it. connection.ReleaseWrite(); connection.Close(); connection = null; } catch (SocketException) { // Unexpected connection loss. Connection isn't working anymore, so close it. connection.ReleaseWrite(); connection.Close(); connection = null; } catch (RemotingException) { // Unexpected connection loss. Connection isn't working anymore, so close it. connection.ReleaseWrite(); connection.Close(); connection = null; } finally { if (connection != null) { connection.ReleaseWrite(); } } }
/// <summary> /// Receives a message over a specified Duplex Channel Connection. /// </summary> /// <param name="connection">Duplex Channel Connection</param> /// <param name="ar">Result (for Async pattern)</param> /// <returns>Received message</returns> public static Message EndReceive(out Connection connection, IAsyncResult ar) { AsyncResult myAr = (AsyncResult)ar; connection = myAr.Connection; try { connection.LockRead(); if (connection.Socket == null) { throw new MessageException("Connection closed.", null, connection); } int bytesRead = connection.Socket.EndReceive(myAr.InternalAsyncResult); if (bytesRead == 16) { Message retVal = new Message(); retVal.Guid = new Guid(myAr.Buffer); BinaryReader reader = connection.Reader; int headerLength = reader.ReadInt32(); MemoryStream headerStream = new MemoryStream(reader.ReadBytes(headerLength)); if (headerStream.Length != headerLength) { throw new Exception("Not enough headers read..."); } retVal.Headers = TransportHeaderWrapper.Deserialize(headerStream); int bodyLength = reader.ReadInt32(); if (bodyLength > 0) { retVal.messageBodyBytes = reader.ReadBytes(bodyLength); if (retVal.messageBodyBytes.Length != bodyLength) { throw new Exception("Not enough body read..."); } System.Diagnostics.Debug.Assert(retVal.MessageBody.CanRead); } Message.BeginReceive(connection, myAr.Callback, myAr.AsyncState); return(retVal); } else if (bytesRead == 0) { throw new MessageException("Connection closed.", null, connection); } else { throw new MessageException("Insufficient data received", null, connection); } } catch (Exception e) { throw new MessageException("Error receiving message", e, connection); } finally { connection.ReleaseRead(); } }