예제 #1
0
        /// <summary>
        /// Connects to a service on a device.
        /// </summary>
        /// <param name="device">
        /// The device to which to connect.
        /// </param>
        /// <param name="port">
        /// The TCP port number to which to connect.
        /// </param>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous task.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> which represents the asynchronous operation, and which returns a <see cref="Stream"/>
        /// which represents the connection with the device. You must dispose of this stream when you are done with it.
        /// </returns>
        public virtual async Task <Stream> ConnectAsync(MuxerDevice device, int port, CancellationToken cancellationToken)
        {
            var(error, stream) = await this.TryConnectAsync(device, port, cancellationToken).ConfigureAwait(false);

            if (error != MuxerError.Success)
            {
                // If you get error 2 (BadDevice) here, you're too late: the service has been shut
                // down because you didn't connect in time.
                throw new MuxerException(
                          $"The device returned an invalid response number when connecting. Expected Success but got {error}",
                          error);
            }

            return(stream);
        }
예제 #2
0
        /// <summary>
        /// Attempts to connect to a service on a device.
        /// </summary>
        /// <param name="device">
        /// The device to which to connect.
        /// </param>
        /// <param name="port">
        /// The TCP port number to which to connect.
        /// </param>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous task.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> which represents the asynchronous operation, and which returns a <see cref="Stream"/>
        /// which represents the connection with the device. You must dispose of this stream when you are done with it.
        /// </returns>
        public virtual async Task <(MuxerError, Stream)> TryConnectAsync(MuxerDevice device, int port, CancellationToken cancellationToken)
        {
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }

            var bigEndianPort = unchecked ((ushort)((port >> 8 & 0xFF) | (port & 0xFF) << 8));

            var protocol = await this.TryConnectToMuxerAsync(cancellationToken).ConfigureAwait(false);

            if (protocol == null)
            {
                this.logger.LogWarning("Could not connect to the server.");
                return(MuxerError.MuxerError, null);
            }

            // Send the connect request to the muxer.
            await protocol.WriteMessageAsync(
                new ConnectMessage()
            {
                DeviceID    = device.DeviceID,
                PortNumber  = bigEndianPort,
                MessageType = MuxerMessageType.Connect,
            },
                cancellationToken).ConfigureAwait(false);

            // Read the response
            var response = await protocol.ReadMessageAsync(cancellationToken).ConfigureAwait(false);

            if (response == null)
            {
                this.logger.LogWarning("The server unexpectedly close the connection when sending the Connect command.");
                return(MuxerError.MuxerError, null);
            }

            var result = (ResultMessage)response;

            if (result.Number != MuxerError.Success)
            {
                return(result.Number, null);
            }

            // The muxer will now forward all messages to the service listening at the port specified on the device.
            // The caller can use this stream (but must dispose of it).
            return(result.Number, protocol.Stream);
        }