public void SignOutWithoutBeingSignedIn() { var endpoints = new Mock <IStoreInformationAboutEndpoints>(); var protocolInfo = new ProtocolInformation( new Version(1, 0), new Uri("net.pipe://localhost/protocol/message/invalid"), new Uri("net.pipe://localhost/protocol/data/invalid")); var channel = new Mock <IProtocolChannel>(); { channel.Setup(c => c.OpenChannel()) .Verifiable(); channel.Setup(c => c.LocalConnectionPointForVersion(It.IsAny <Version>())) .Returns(protocolInfo); channel.Setup(c => c.CloseChannel()) .Verifiable(); } var pipe = new Mock <IDirectIncomingMessages>(); Func <ChannelTemplate, EndpointId, Tuple <IProtocolChannel, IDirectIncomingMessages> > channelBuilder = (template, id) => new Tuple <IProtocolChannel, IDirectIncomingMessages>(channel.Object, pipe.Object); var diagnostics = new SystemDiagnostics((log, s) => { }, null); var layer = new ProtocolLayer( endpoints.Object, channelBuilder, new[] { ChannelTemplate.NamedPipe, }, diagnostics); layer.SignOut(); Assert.IsFalse(layer.IsSignedIn); channel.Verify(c => c.CloseChannel(), Times.Never()); }
public void CloseChannelTo() { var endpointId = new EndpointId("id"); var endpointInfo = new ProtocolInformation( ProtocolVersions.V1, new Uri("http://localhost/messages"), new Uri("http://localhost/data")); var msg = new EndpointDisconnectMessage(endpointId); var messageProxy = new Mock <IMessageSendingEndpoint>(); var messageDisposable = messageProxy.As <IDisposable>(); var dataProxy = new Mock <IDataTransferingEndpoint>(); var dataDisposable = dataProxy.As <IDisposable>(); var localEndpoint = new EndpointId("local"); Func <ProtocolInformation, IMessageSendingEndpoint> messageBuilder = id => messageProxy.Object; Func <ProtocolInformation, IDataTransferingEndpoint> dataBuilder = id => dataProxy.Object; var sender = new SendingEndpoint(localEndpoint, messageBuilder, dataBuilder); sender.Send(endpointInfo, msg, 1); Assert.AreEqual(1, sender.KnownEndpoints().Count()); sender.CloseChannelTo(endpointInfo); Assert.AreEqual(0, sender.KnownEndpoints().Count()); }
public void SendMessageToUnknownReceiver() { var endpointId = new EndpointId("id"); var endpointInfo = new ProtocolInformation( ProtocolVersions.V1, new Uri("http://localhost/messages"), new Uri("http://localhost/data")); var msg = new EndpointDisconnectMessage(endpointId); var messageProxy = new Mock <IMessageSendingEndpoint>(); { messageProxy.Setup(p => p.Send(It.IsAny <ICommunicationMessage>(), It.IsAny <int>())) .Callback <ICommunicationMessage, int>((input, retries) => Assert.AreSame(msg, input)); } var dataProxy = new Mock <IDataTransferingEndpoint>(); { dataProxy.Setup(p => p.Send(It.IsAny <DataTransferMessage>(), It.IsAny <int>())) .Verifiable(); } var localEndpoint = new EndpointId("local"); Func <ProtocolInformation, IMessageSendingEndpoint> builder = id => messageProxy.Object; Func <ProtocolInformation, IDataTransferingEndpoint> dataBuilder = id => dataProxy.Object; var sender = new SendingEndpoint(localEndpoint, builder, dataBuilder); sender.Send(endpointInfo, msg, 1); Assert.AreEqual(1, sender.KnownEndpoints().Count()); dataProxy.Verify(p => p.Send(It.IsAny <DataTransferMessage>(), It.IsAny <int>()), Times.Never()); }
internal bool GetFixedSize(ref int size) { if (size < 0) { return(false); } if (_data.Length == 0) { return(true); } // Sensible? size = ProtocolInformation.Padded(size, Alignment); if (_data.Length == 1) { int valueSize = GetSize(this[0]); if (valueSize == -1) { return(false); } size += valueSize; return(true); } if (IsStructlike) { foreach (Signature sig in GetParts()) { if (!sig.GetFixedSize(ref size)) { return(false); } } return(true); } if (IsArray || IsDict) { return(false); } if (IsStruct) { foreach (Signature sig in GetFieldSignatures()) { if (!sig.GetFixedSize(ref size)) { return(false); } } return(true); } // Any other cases? throw new Exception(); }
/// <summary> /// Transfers the data to the receiving endpoint. /// </summary> /// <param name="receivingEndpoint">The connection information for the endpoint that will receive the data stream.</param> /// <param name="filePath">The file path to the file that should be transferred.</param> /// <param name="token">The cancellation token that is used to cancel the task if necessary.</param> /// <param name="scheduler">The scheduler that is used to run the return task with.</param> /// <param name="maximumNumberOfRetries">The maximum number of times the endpoint will try to send the message if delivery fails.</param> /// <returns> /// An task that indicates when the transfer is complete. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="receivingEndpoint"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="filePath"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="filePath"/> is <see langword="null" />. /// </exception> /// <exception cref="FailedToSendMessageException"> /// Thrown when the channel fails to deliver the message to the remote endpoint. /// </exception> public Task TransferData( ProtocolInformation receivingEndpoint, string filePath, CancellationToken token, TaskScheduler scheduler = null, int maximumNumberOfRetries = CommunicationConstants.DefaultMaximuNumberOfRetriesForMessageSending) { { Lokad.Enforce.Argument(() => receivingEndpoint); Lokad.Enforce.Argument(() => filePath); Lokad.Enforce.Argument(() => filePath, Lokad.Rules.StringIs.NotEmpty); } var sender = SenderForEndpoint(receivingEndpoint); return(Task.Factory.StartNew( () => { // Don't catch any exception because the task will store them if we don't catch them. using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { sender.Send(receivingEndpoint, file, maximumNumberOfRetries); } }, token, TaskCreationOptions.LongRunning, scheduler ?? TaskScheduler.Default)); }
public void ToVersioned() { var input = new ProtocolInformation(new Version(1, 2, 3, 4), new Uri("http://localhost/protocol/invalid")); var output = ChannelInformationToTransportConverter.ToVersioned(input); Assert.AreSame(input.Version, output.ProtocolVersion); Assert.AreSame(input.MessageAddress, output.Address); }
/// <summary> /// Initializes a new instance of the <see cref="EndpointConnectMessage"/> class. /// </summary> /// <param name="origin">The ID of the endpoint that send the message.</param> /// <param name="discoveryInformation">The object containing the information about the discovery channel for the remote endpoint.</param> /// <param name="protocolInformation">The object containing the information about the protocol channels for the remote endpoint.</param> /// <param name="information"> /// The information describing the version of the communication protocol /// used by the sender, the desired communication API's for the sender and /// the available communication API's provided by the sender. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="origin"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="discoveryInformation"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="protocolInformation"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="information"/> is <see langword="null" />. /// </exception> public EndpointConnectMessage( EndpointId origin, DiscoveryInformation discoveryInformation, ProtocolInformation protocolInformation, ProtocolDescription information) : this(origin, new MessageId(), discoveryInformation, protocolInformation, information) { }
public void Create() { var version = new Version(1, 2, 3, 4); var message = new Uri("http://localhost/message/invalid"); var data = new Uri("http://localhost/data/invalid"); var info = new ProtocolInformation(version, message, data); Assert.AreSame(version, info.Version); Assert.AreSame(message, info.MessageAddress); Assert.AreSame(data, info.DataAddress); }
/// <summary> /// Indicates that the remote endpoint has disconnected. /// </summary> /// <param name="endpoint">The ID number of the endpoint that has disconnected.</param> public void EndpointDisconnected(ProtocolInformation endpoint) { lock (m_Lock) { var version = endpoint.Version; if (m_SendingEndpoints.ContainsKey(version)) { var sender = m_SendingEndpoints[version]; sender.CloseChannelTo(endpoint); } } }
/// <summary> /// Translates the current version of the <see cref="EndpointInformation"/> to the <see cref="VersionedChannelInformation"/>. /// </summary> /// <param name="info">The channel information describing the available protocol channel.</param> /// <returns>A object describing the versioned channel information.</returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="info"/> is <see langword="null" />. /// </exception> public static VersionedChannelInformation ToVersioned(ProtocolInformation info) { { Lokad.Enforce.Argument(() => info); } return(new VersionedChannelInformation { ProtocolVersion = info.Version, Address = info.MessageAddress }); }
/// <summary> /// Sends the given message. /// </summary> /// <param name="endpoint">The endpoint to which the message should be send.</param> /// <param name="message">The message to be send.</param> /// <param name="maximumNumberOfRetries">The maximum number of times the endpoint will try to send the message if delivery fails.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="endpoint"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="message"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown if <paramref name="maximumNumberOfRetries"/> is smaller than 1. /// </exception> public void Send(ProtocolInformation endpoint, ICommunicationMessage message, int maximumNumberOfRetries) { { Lokad.Enforce.Argument(() => endpoint); Lokad.Enforce.Argument(() => message); Lokad.Enforce.With <ArgumentOutOfRangeException>( maximumNumberOfRetries > 0, Resources.Exceptions_Messages_NumberOfRetriesShouldBeLargerThanZero); } var channel = MessageChannelFor(endpoint); channel.Send(message, maximumNumberOfRetries); }
private ISendingEndpoint SenderForEndpoint(ProtocolInformation info) { var protocolVersion = info.Version; lock (m_Lock) { if (!m_SendingEndpoints.ContainsKey(protocolVersion)) { var newSender = m_SenderBuilder(m_Id, BuildMessageSendingProxy, BuildDataTransferProxy); m_SendingEndpoints.Add(protocolVersion, newSender); } return(m_SendingEndpoints[protocolVersion]); } }
/// <summary> /// Sends the given message to the receiving endpoint. /// </summary> /// <param name="endpoint">The connection information for the endpoint to which the message should be send.</param> /// <param name="message">The message that should be send.</param> /// <param name="maximumNumberOfRetries">The maximum number of times the endpoint will try to send the message if delivery fails.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="endpoint"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="message"/> is <see langword="null" />. /// </exception> /// <exception cref="FailedToSendMessageException"> /// Thrown when the channel fails to deliver the message to the remote endpoint. /// </exception> public void Send(ProtocolInformation endpoint, ICommunicationMessage message, int maximumNumberOfRetries) { { Lokad.Enforce.Argument(() => endpoint); Lokad.Enforce.Argument(() => message); } var sender = SenderForEndpoint(endpoint); if (sender == null) { throw new EndpointNotContactableException(); } sender.Send(endpoint, message, maximumNumberOfRetries); }
public void SendDataToKnownReceiver() { var text = "Hello world."; var data = new MemoryStream(); var writer = new StreamWriter(data); writer.Write(text); data.Position = 0; var localEndpoint = new EndpointId("local"); var endpointInfo = new ProtocolInformation( ProtocolVersions.V1, new Uri("http://localhost/messages"), new Uri("http://localhost/data")); var messageProxy = new Mock <IMessageSendingEndpoint>(); { messageProxy.Setup(p => p.Send(It.IsAny <ICommunicationMessage>(), It.IsAny <int>())) .Verifiable(); } var dataProxy = new Mock <IDataTransferingEndpoint>(); { dataProxy.Setup(p => p.Send(It.IsAny <DataTransferMessage>(), It.IsAny <int>())) .Callback <DataTransferMessage, int>( (msg, retries) => { Assert.AreSame(localEndpoint, msg.SendingEndpoint); Assert.AreSame(data, msg.Data); }) .Verifiable(); } Func <ProtocolInformation, IMessageSendingEndpoint> builder = id => messageProxy.Object; Func <ProtocolInformation, IDataTransferingEndpoint> dataBuilder = id => dataProxy.Object; var sender = new SendingEndpoint(localEndpoint, builder, dataBuilder); sender.Send(endpointInfo, data, 1); Assert.AreEqual(1, sender.KnownEndpoints().Count()); messageProxy.Verify(p => p.Send(It.IsAny <ICommunicationMessage>(), It.IsAny <int>()), Times.Never()); dataProxy.Verify(p => p.Send(It.IsAny <DataTransferMessage>(), It.IsAny <int>()), Times.Exactly(1)); sender.Send(endpointInfo, data, 1); Assert.AreEqual(1, sender.KnownEndpoints().Count()); messageProxy.Verify(p => p.Send(It.IsAny <ICommunicationMessage>(), It.IsAny <int>()), Times.Never()); dataProxy.Verify(p => p.Send(It.IsAny <DataTransferMessage>(), It.IsAny <int>()), Times.Exactly(2)); }
/// <summary> /// Initializes a new instance of the <see cref="EndpointConnectMessage"/> class. /// </summary> /// <param name="origin">The ID of the endpoint that send the message.</param> /// <param name="id">The ID of the current message.</param> /// <param name="discoveryInformation">The object containing the information about the discovery channel for the remote endpoint.</param> /// <param name="protocolInformation">The object containing the information about the protocol channels for the remote endpoint.</param> /// <param name="information"> /// The information describing the version of the communication protocol /// used by the sender, the desired communication API's for the sender and /// the available communication API's provided by the sender. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="origin"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="id"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="discoveryInformation"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="protocolInformation"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="information"/> is <see langword="null" />. /// </exception> public EndpointConnectMessage( EndpointId origin, MessageId id, DiscoveryInformation discoveryInformation, ProtocolInformation protocolInformation, ProtocolDescription information) : base(origin, id) { { Lokad.Enforce.Argument(() => discoveryInformation); Lokad.Enforce.Argument(() => protocolInformation); Lokad.Enforce.Argument(() => information); } DiscoveryInformation = discoveryInformation; ProtocolInformation = protocolInformation; Information = information; }
public void Invoke() { EndpointInformation processedChannel = null; ProtocolDescription processedDescription = null; MessageId processedMessageId = null; var sink = new Mock <IHandleProtocolHandshakes>(); { sink.Setup(s => s.ContinueHandshakeWith( It.IsAny <EndpointInformation>(), It.IsAny <ProtocolDescription>(), It.IsAny <MessageId>())) .Callback <EndpointInformation, ProtocolDescription, MessageId>((e, t, u) => { processedChannel = e; processedDescription = t; processedMessageId = u; }); } var channelTypes = new[] { ChannelTemplate.TcpIP }; var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null); var action = new EndpointConnectProcessAction(sink.Object, channelTypes, systemDiagnostics); var id = new EndpointId("id"); var discovery = new DiscoveryInformation(new Uri("http://localhost/discovery/invalid")); var protocol = new ProtocolInformation( new Version(1, 0), new Uri("http://localhost/protocol/message/invalid"), new Uri("http://localhost/protocol/data/invalid")); var description = new ProtocolDescription(new List <CommunicationSubject>()); var msg = new EndpointConnectMessage(id, discovery, protocol, description); action.Invoke(msg); Assert.AreEqual(msg.Id, processedMessageId); Assert.AreEqual(id, processedChannel.Id); Assert.AreSame(discovery, processedChannel.DiscoveryInformation); Assert.AreSame(protocol, processedChannel.ProtocolInformation); Assert.AreSame(description, processedDescription); }
/// <summary> /// Transfers the stream to the given endpoint. /// </summary> /// <param name="endpoint">The endpoint to which the data should be send.</param> /// <param name="data">The data to be send.</param> /// <param name="maximumNumberOfRetries">The maximum number of times the endpoint will try to transfer the data if delivery fails.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="endpoint"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="data"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown if <paramref name="maximumNumberOfRetries"/> is smaller than 1. /// </exception> public void Send(ProtocolInformation endpoint, Stream data, int maximumNumberOfRetries) { { Lokad.Enforce.Argument(() => endpoint); Lokad.Enforce.Argument(() => data); Lokad.Enforce.With <ArgumentOutOfRangeException>( maximumNumberOfRetries > 0, Resources.Exceptions_Messages_NumberOfRetriesShouldBeLargerThanZero); } var channel = DataChannelFor(endpoint); var msg = new DataTransferMessage { SendingEndpoint = m_LocalEndpoint, Data = data, }; channel.Send(msg, maximumNumberOfRetries); }
/// <summary> /// Opens the channel and provides information on how to connect to the given channel. /// </summary> public void OpenChannel() { lock (m_Lock) { foreach (var version in ProtocolVersions.SupportedVersions()) { if (m_MessagePipesByVersion.ContainsKey(version) || m_DataPipesByVersion.ContainsKey(version)) { CloseChannel(version); } var dataUri = CreateAndStoreDataChannelForProtocolVersion(version); var messageUri = CreateAndStoreMessageChannelForProtocolVersion(version); var localConnection = new ProtocolInformation(version, messageUri, dataUri); m_LocalConnectionPoints.Add(localConnection); } } }
private IDataTransferingEndpoint DataChannelFor(ProtocolInformation endpoint) { lock (m_Lock) { if (!m_EndpointMap.ContainsKey(endpoint)) { m_EndpointMap.Add(endpoint, new Tuple <IMessageSendingEndpoint, IDataTransferingEndpoint>(null, null)); } if (m_EndpointMap[endpoint].Item2 == null) { var dataChannel = m_DataSenderBuilder(endpoint); var tuple = m_EndpointMap[endpoint]; m_EndpointMap[endpoint] = new Tuple <IMessageSendingEndpoint, IDataTransferingEndpoint>(tuple.Item1, dataChannel); } return(m_EndpointMap[endpoint].Item2); } }
public void Create() { var sender = new EndpointId("sendingEndpoint"); var discovery = new DiscoveryInformation(new Uri("http://localhost/discovery/invalid")); var protocol = new ProtocolInformation( new Version(1, 0), new Uri("http://localhost/protocol/message/invalid"), new Uri("http://localhost/protocol/data/invalid")); var description = new ProtocolDescription(new List <CommunicationSubject>()); var msg = new EndpointConnectMessage( sender, discovery, protocol, description); Assert.IsNotNull(msg.Id); Assert.AreSame(sender, msg.Sender); Assert.AreSame(discovery, msg.DiscoveryInformation); Assert.AreSame(protocol, msg.ProtocolInformation); Assert.AreSame(description, msg.Information); }
/// <summary> /// Closes the channel that connects to the given endpoint. /// </summary> /// <param name="endpoint">The ID number of the endpoint to which the connection should be closed.</param> public void CloseChannelTo(ProtocolInformation endpoint) { lock (m_Lock) { if (!m_EndpointMap.ContainsKey(endpoint)) { return; } var tuple = m_EndpointMap[endpoint]; m_EndpointMap.Remove(endpoint); if (tuple.Item1 != null) { tuple.Item1.Dispose(); } if (tuple.Item2 != null) { tuple.Item2.Dispose(); } } }
public void RecentlyConnectedEndpoint() { var uri = new Uri("net.pipe://localhost/pipe/discovery/"); var versionedUri = new Uri(uri, new Uri("/1.0", UriKind.Relative)); var protocolInfo = new ProtocolInformation( new Version(2, 0), new Uri("http://localhost/protocol/message/invalid"), new Uri("http://localhost/protocol/data/invalid")); var translator = new Mock <ITranslateVersionedChannelInformation>(); { translator.Setup(t => t.FromUri(It.IsAny <Uri>())) .Callback <Uri>(u => Assert.AreEqual(versionedUri, u)) .Returns(protocolInfo); } var translators = new[] { new Tuple <Version, ITranslateVersionedChannelInformation>(new Version(1, 0), translator.Object), }; var configuration = new Mock <IConfiguration>(); { configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>())) .Returns(false); } var template = new NamedPipeDiscoveryChannelTemplate(configuration.Object); Func <ChannelTemplate, IDiscoveryChannelTemplate> templateBuilder = t => template; var diagnostics = new SystemDiagnostics((l, s) => { }, null); var discovery = new ManualDiscoverySource( translators, templateBuilder, diagnostics); var eventWasRaised = false; discovery.OnEndpointBecomingAvailable += (s, e) => { eventWasRaised = true; }; discovery.StartDiscovery(); var channels = new[] { new Tuple <Version, Uri>(new Version(1, 0), versionedUri), }; var receiver = new BootstrapEndpoint(channels); var host = new ServiceHost(receiver, uri); var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { TransferMode = TransferMode.Buffered, }; var address = string.Format("{0}_{1}", "ThroughNamedPipe", Process.GetCurrentProcess().Id); var endpoint = host.AddServiceEndpoint(typeof(IBootstrapEndpoint), binding, address); host.Open(); try { discovery.RecentlyConnectedEndpoint( EndpointIdExtensions.CreateEndpointIdForCurrentProcess(), endpoint.ListenUri); } finally { host.Close(); } Assert.IsTrue(eventWasRaised); }
public async Task <Message> ReceiveMessageAsync() { try { int bytesRead = await ReadCountAsync(_headerReadBuffer, 0, 16, _fileDescriptors).ConfigureAwait(false); if (bytesRead == 0) { return(null); } if (bytesRead != 16) { throw new ProtocolException("Header read length mismatch: " + bytesRead + " of expected " + "16"); } EndianFlag endianness = (EndianFlag)_headerReadBuffer[0]; MessageReader reader = new MessageReader(endianness, new ArraySegment <byte>(_headerReadBuffer)); //discard endian byte, message type and flags, which we don't care about here reader.Seek(3); byte version = reader.ReadByte(); if (version != ProtocolInformation.Version) { throw new NotSupportedException("Protocol version '" + version.ToString() + "' is not supported"); } uint bodyLength = reader.ReadUInt32(); //discard _methodSerial reader.ReadUInt32(); uint headerLength = reader.ReadUInt32(); int bodyLen = (int)bodyLength; int toRead = (int)headerLength; //we fixup to include the padding following the header toRead = ProtocolInformation.Padded(toRead, 8); long msgLength = toRead + bodyLen; if (msgLength > ProtocolInformation.MaxMessageLength) { throw new ProtocolException("Message length " + msgLength + " exceeds maximum allowed " + ProtocolInformation.MaxMessageLength + " bytes"); } byte[] header = new byte[16 + toRead]; Array.Copy(_headerReadBuffer, header, 16); bytesRead = await ReadCountAsync(header, 16, toRead, _fileDescriptors).ConfigureAwait(false); if (bytesRead != toRead) { throw new ProtocolException("Message header length mismatch: " + bytesRead + " of expected " + toRead); } var messageHeader = Header.FromBytes(new ArraySegment <byte>(header)); byte[] body = null; //read the body if (bodyLen != 0) { body = new byte[bodyLen]; bytesRead = await ReadCountAsync(body, 0, bodyLen, _fileDescriptors).ConfigureAwait(false); if (bytesRead != bodyLen) { throw new ProtocolException("Message body length mismatch: " + bytesRead + " of expected " + bodyLen); } } if (_fileDescriptors.Count < messageHeader.NumberOfFds) { throw new ProtocolException("File descriptor length mismatch: " + _fileDescriptors.Count + " of expected " + messageHeader.NumberOfFds); } Message msg = new Message( messageHeader, body, messageHeader.NumberOfFds == 0 ? null : _fileDescriptors.Count == messageHeader.NumberOfFds ? _fileDescriptors.ToArray() : _fileDescriptors.Take((int)messageHeader.NumberOfFds).ToArray() ); _fileDescriptors.RemoveRange(0, (int)messageHeader.NumberOfFds); return(msg); } catch { foreach (var fd in _fileDescriptors) { CloseSafeHandle.close(fd.Handle); } throw; } }
public void TransferData() { var path = TempFile(); var text = "Some random text"; using (var writer = new StreamWriter(path, false)) { writer.Write(text); } var id = new EndpointId("a"); var endpointInfo = new ProtocolInformation( ProtocolVersions.V1, new Uri("http://localhost/messages"), new Uri("http://localhost/data")); var template = new Mock <IProtocolChannelTemplate>(); var messageUri = new Uri("http://localhost/messages/invalid"); var dataUri = new Uri("http://localhost/data/invalid"); var host = new Mock <IHoldServiceConnections>(); { host.Setup( h => h.OpenChannel( It.IsAny <IReceiveInformationFromRemoteEndpoints>(), It.IsAny <Func <ServiceHost, ServiceEndpoint> >())) .Returns <IReceiveInformationFromRemoteEndpoints, Func <ServiceHost, ServiceEndpoint> >( (r, f) => r is IMessagePipe ? messageUri : dataUri) .Verifiable(); host.Setup(h => h.CloseConnection()) .Verifiable(); } Func <IHoldServiceConnections> hostBuilder = () => host.Object; var messagePipe = new Mock <IMessagePipe>(); Func <Version, Tuple <Type, IMessagePipe> > messageReceiverBuilder = version => new Tuple <Type, IMessagePipe>(typeof(IMessagePipe), messagePipe.Object); var dataPipe = new Mock <IDataPipe>(); Func <Version, Tuple <Type, IDataPipe> > dataReceiverBuilder = version => new Tuple <Type, IDataPipe>(typeof(IDataPipe), dataPipe.Object); var sendingEndpoint = new Mock <ISendingEndpoint>(); { sendingEndpoint.Setup(e => e.KnownEndpoints()) .Returns(new[] { endpointInfo }); sendingEndpoint.Setup(e => e.CloseChannelTo(It.IsAny <ProtocolInformation>())) .Verifiable(); sendingEndpoint.Setup(e => e.Send(It.IsAny <ProtocolInformation>(), It.IsAny <Stream>(), It.IsAny <int>())) .Callback <ProtocolInformation, Stream, int>( (e, m, r) => { string fileText; using (var reader = new StreamReader(m)) { fileText = reader.ReadToEnd(); } Assert.AreEqual(text, fileText); }) .Verifiable(); } BuildSendingEndpoint senderBuilder = (endpoint, builder, endpointBuilder) => sendingEndpoint.Object; var messageEndpoint = new Mock <IMessageSendingEndpoint>(); Func <Version, Uri, IMessageSendingEndpoint> versionedMessageSenderBuilder = (version, uri) => messageEndpoint.Object; var dataEndpoint = new Mock <IDataTransferingEndpoint>(); Func <Version, Uri, IDataTransferingEndpoint> versionedDataSenderBuilder = (version, uri) => dataEndpoint.Object; var channel = new ProtocolChannel( id, template.Object, hostBuilder, messageReceiverBuilder, dataReceiverBuilder, senderBuilder, versionedMessageSenderBuilder, versionedDataSenderBuilder); channel.OpenChannel(); var protocols = channel.LocalConnectionPoints().ToList(); Assert.AreEqual(1, protocols.Count()); var task = channel.TransferData(endpointInfo, path, new CancellationToken(), new CurrentThreadTaskScheduler(), 1); task.Wait(); sendingEndpoint.Verify(e => e.Send(It.IsAny <ProtocolInformation>(), It.IsAny <Stream>(), It.IsAny <int>()), Times.Once()); }
public void Send() { var id = new EndpointId("a"); var endpointInfo = new ProtocolInformation( ProtocolVersions.V1, new Uri("http://localhost/messages"), new Uri("http://localhost/data")); var template = new Mock <IProtocolChannelTemplate>(); var messageUri = new Uri("http://localhost/messages/invalid"); var dataUri = new Uri("http://localhost/data/invalid"); var host = new Mock <IHoldServiceConnections>(); { host.Setup( h => h.OpenChannel( It.IsAny <IReceiveInformationFromRemoteEndpoints>(), It.IsAny <Func <ServiceHost, ServiceEndpoint> >())) .Returns <IReceiveInformationFromRemoteEndpoints, Func <ServiceHost, ServiceEndpoint> >( (r, f) => r is IMessagePipe ? messageUri : dataUri) .Verifiable(); host.Setup(h => h.CloseConnection()) .Verifiable(); } Func <IHoldServiceConnections> hostBuilder = () => host.Object; var messagePipe = new Mock <IMessagePipe>(); Func <Version, Tuple <Type, IMessagePipe> > messageReceiverBuilder = version => new Tuple <Type, IMessagePipe>(typeof(IMessagePipe), messagePipe.Object); var dataPipe = new Mock <IDataPipe>(); Func <Version, Tuple <Type, IDataPipe> > dataReceiverBuilder = version => new Tuple <Type, IDataPipe>(typeof(IDataPipe), dataPipe.Object); var msg = new SuccessMessage(id, new MessageId()); var sendingEndpoint = new Mock <ISendingEndpoint>(); { sendingEndpoint.Setup(e => e.KnownEndpoints()) .Returns(new[] { endpointInfo }); sendingEndpoint.Setup(e => e.CloseChannelTo(It.IsAny <ProtocolInformation>())) .Verifiable(); sendingEndpoint.Setup(e => e.Send(It.IsAny <ProtocolInformation>(), It.IsAny <ICommunicationMessage>(), It.IsAny <int>())) .Callback <ProtocolInformation, ICommunicationMessage, int>((e, m, r) => Assert.AreSame(msg, m)) .Verifiable(); } BuildSendingEndpoint senderBuilder = (endpoint, builder, endpointBuilder) => sendingEndpoint.Object; var messageEndpoint = new Mock <IMessageSendingEndpoint>(); Func <Version, Uri, IMessageSendingEndpoint> versionedMessageSenderBuilder = (version, uri) => messageEndpoint.Object; var dataEndpoint = new Mock <IDataTransferingEndpoint>(); Func <Version, Uri, IDataTransferingEndpoint> versionedDataSenderBuilder = (version, uri) => dataEndpoint.Object; var channel = new ProtocolChannel( id, template.Object, hostBuilder, messageReceiverBuilder, dataReceiverBuilder, senderBuilder, versionedMessageSenderBuilder, versionedDataSenderBuilder); channel.OpenChannel(); var protocols = channel.LocalConnectionPoints().ToList(); Assert.AreEqual(1, protocols.Count()); channel.Send(endpointInfo, msg, 1); sendingEndpoint.Verify(e => e.Send(It.IsAny <ProtocolInformation>(), It.IsAny <ICommunicationMessage>(), It.IsAny <int>()), Times.Once()); }
Message ReadMessageReal() { byte[] header = null; byte[] body = null; UnixFDArray fdArray = Connection.UnixFDSupported ? new UnixFDArray() : null; int read; //16 bytes is the size of the fixed part of the header if (readBuffer == null) { readBuffer = new byte[16]; } byte[] hbuf = readBuffer; read = Read(hbuf, 0, 16, fdArray); if (read == 0) { return(null); } if (read != 16) { throw new Exception("Header read length mismatch: " + read + " of expected " + "16"); } EndianFlag endianness = (EndianFlag)hbuf[0]; MessageReader reader = new MessageReader(endianness, hbuf); //discard endian byte, message type and flags, which we don't care about here reader.Seek(3); byte version = reader.ReadByte(); if (version < ProtocolInformation.MinVersion || version > ProtocolInformation.MaxVersion) { throw new NotSupportedException("Protocol version '" + version.ToString() + "' is not supported"); } if (ProtocolInformation.Verbose) { if (version != ProtocolInformation.Version) { Console.Error.WriteLine("Warning: Protocol version '" + version.ToString() + "' is not explicitly supported but may be compatible"); } } uint bodyLength = reader.ReadUInt32(); //discard serial reader.ReadUInt32(); uint headerLength = reader.ReadUInt32(); int bodyLen = (int)bodyLength; int toRead = (int)headerLength; //we fixup to include the padding following the header toRead = ProtocolInformation.Padded(toRead, 8); long msgLength = toRead + bodyLen; if (msgLength > ProtocolInformation.MaxMessageLength) { throw new Exception("Message length " + msgLength + " exceeds maximum allowed " + ProtocolInformation.MaxMessageLength + " bytes"); } header = new byte[16 + toRead]; Array.Copy(hbuf, header, 16); read = Read(header, 16, toRead, fdArray); if (read != toRead) { throw new Exception("Message header length mismatch: " + read + " of expected " + toRead); } //read the body if (bodyLen != 0) { body = new byte[bodyLen]; read = Read(body, 0, bodyLen, fdArray); if (read != bodyLen) { throw new Exception("Message body length mismatch: " + read + " of expected " + bodyLen); } } Message msg = Message.FromReceivedBytes(Connection, header, body, fdArray); return(msg); }
public void UploadDataWithUncontactableEndpoint() { var endpoints = new Mock <IStoreInformationAboutEndpoints>(); { endpoints.Setup(e => e.CanCommunicateWithEndpoint(It.IsAny <EndpointId>())) .Returns(false); } var protocolInfo = new ProtocolInformation( new Version(1, 0), new Uri("net.pipe://localhost/protocol/message/invalid"), new Uri("net.pipe://localhost/protocol/data/invalid")); var endpoint = new EndpointId("A"); var file = "B"; var channel = new Mock <IProtocolChannel>(); { channel.Setup(c => c.OpenChannel()) .Verifiable(); channel.Setup(c => c.LocalConnectionPointForVersion(It.IsAny <Version>())) .Returns(protocolInfo); channel.Setup( c => c.TransferData( It.IsAny <ProtocolInformation>(), It.IsAny <string>(), It.IsAny <CancellationToken>(), It.IsAny <TaskScheduler>(), It.IsAny <int>())) .Callback <ProtocolInformation, string, CancellationToken, TaskScheduler, int>( (e, p, c, s, r) => { Assert.AreSame(protocolInfo, e); Assert.AreSame(file, p); }) .Returns <EndpointId, string, CancellationToken, TaskScheduler>( (e, p, c, s) => Task.Factory.StartNew(() => { }, c, TaskCreationOptions.None, s)) .Verifiable(); } var pipe = new Mock <IDirectIncomingMessages>(); Func <ChannelTemplate, EndpointId, Tuple <IProtocolChannel, IDirectIncomingMessages> > channelBuilder = (template, id) => { return(new Tuple <IProtocolChannel, IDirectIncomingMessages>(channel.Object, pipe.Object)); }; var diagnostics = new SystemDiagnostics((log, s) => { }, null); var layer = new ProtocolLayer( endpoints.Object, channelBuilder, new[] { ChannelTemplate.NamedPipe, }, diagnostics); layer.SignIn(); Assert.Throws <EndpointNotContactableException>( () => layer.UploadData(endpoint, file, new CancellationToken(), new CurrentThreadTaskScheduler(), 1)); channel.Verify(c => c.OpenChannel(), Times.Once()); channel.Verify( c => c.TransferData( It.IsAny <ProtocolInformation>(), It.IsAny <string>(), It.IsAny <CancellationToken>(), It.IsAny <TaskScheduler>(), It.IsAny <int>()), Times.Never()); }
/// <summary> /// Convert Major/Minor version info in the ProtocolInformation object to a known R2000ProtocolVersion /// </summary> /// <param name="pi"></param> /// <returns></returns> public static R2000ProtocolVersion GetProtocolVersion(this ProtocolInformation pi) { var asInt = pi.VersionMajor * 100 + pi.VersionMinor; return((R2000ProtocolVersion)asInt); }
private IDataTransferingEndpoint BuildDataTransferProxy(ProtocolInformation info) { return(m_VersionedDataSenderBuilder(info.Version, info.DataAddress)); }
private IMessageSendingEndpoint BuildMessageSendingProxy(ProtocolInformation info) { return(m_VersionedMessageSenderBuilder(info.Version, info.MessageAddress)); }