/// <summary>
        /// expect packet from transport.
        /// </summary>
        /// <param name="buffer">
        /// a BytesBuffer object that contains the received data from endpoint.
        /// </param>
        /// <param name="decoder">
        /// a DecodePacketCallback delegate that is used to decode packet from buffer.
        /// </param>
        /// <param name="endpoint">
        /// an object that specifies the endpoint for decoder.<para/>
        /// remember: this endpoint must be the endpoint that is returned to the user,
        /// that is the endpoint return by Connect().
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="packetCache">
        /// a list that contains the stackpackets.
        /// </param>
        /// <returns>
        /// a StackPacket object that specifies the received packet.
        /// </returns>
        public static StackPacket Visit(
            BytesBuffer buffer, DecodePacketCallback decoder, object endpoint,
            TimeSpan timeout, SyncFilterQueue <StackPacket> packetCache)
        {
            // get the packet in packet list.
            if (packetCache.Count > 0)
            {
                return(Utility.GetOne <StackPacket>(packetCache, null));
            }

            // the consumed length of decoder.
            int consumedLength = 0;

            // decode packet, return null or at least one packet.
            StackPacket[] packets = ExpectMultiPacketsVisitor.Visit(
                buffer, decoder, endpoint, timeout, out consumedLength);

            // packet is null, buffer is closed, no packet will come.
            if (packets == null)
            {
                return(null);
            }

            // if packet arrived, add to packet list, and return the first.
            foreach (StackPacket packet in packets)
            {
                packetCache.Enqueue(packet);
            }

            return(Utility.GetOne <StackPacket>(packetCache, null));
        }
Example #2
0
        /// <summary>
        ///  Constructor. Initialize member variables.
        /// </summary>
        /// <param name="transportConfig">Provides the transport parameters.</param>
        /// <param name="decodePacketCallback">Callback of decoding packet.</param>
        /// <param name="certificate">X509 certificate.</param>
        public RdpbcgrServerTransportStack(
            RdpbcgrServer rdpbcgrServer,
            RdpcbgrServerTransportConfig transportConfig,
            DecodePacketCallback decodePacketCallback,
            X509Certificate2 certificate)
        {
            this.rdpbcgrServer = rdpbcgrServer;
            this.config        = transportConfig;
            if (this.config == null)
            {
                throw new System.InvalidCastException("TcpServerTransport needs SocketTransportConfig.");
            }

            this.decoder     = decodePacketCallback;
            this.packetQueue = new QueueManager();
            this.listenSock  = new Socket(transportConfig.LocalIpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            this.listenSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            this.streamType = transportConfig.StreamType;
            IPEndPoint endPoint = new IPEndPoint(config.LocalIpAddress, config.LocalIpPort);

            this.listenSock.Bind(endPoint);
            this.listenSock.Listen(config.MaxConnections);
            this.acceptThread     = new Thread(new ThreadStart(AcceptLoop));
            this.receivingStreams = new Dictionary <Socket, RdpbcgrReceiveThread>();
            this.cert             = certificate;
        }
Example #3
0
        /// <summary>
        /// Create a new thread to receive the data from remote host.
        /// </summary>
        /// <param name="packetQueueManager">Store all event packets generated in receiving loop.</param>
        /// <param name="decodePacketCallback">Callback of packet decode.</param>
        /// <param name="stream">The stream used to receive data.</param>
        /// <param name="bufferSize">Buffer size used in receiving data.</param>
        public RdpbcgrReceiveThread(
            object endPoint,
            QueueManager packetQueueManager,
            DecodePacketCallback decodePacketCallback,
            Stream stream,
            int bufferSize,
            RdpbcgrServer rdpbcgrServer)
        {
            if (packetQueueManager == null)
            {
                throw new ArgumentNullException("packetQueueManager");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            // Initialize variable.
            this.endPointIdentity = endPoint;
            this.packetQueue      = packetQueueManager;
            this.decoder          = decodePacketCallback;
            this.receiveStream    = stream;
            this.maxBufferSize    = bufferSize;
            this.rdpbcgrServer    = rdpbcgrServer;
            this.receivingThread  = new Thread((new ThreadStart(ReceiveLoop)));
        }
Example #4
0
        /// <summary>
        ///  Constructor. Initialize member variables.
        /// </summary>
        /// <param name="transportConfig">Provides the transport parameters.</param>
        /// <param name="decodePacketCallback">Callback of decoding packet.</param>
        public RdpbcgrServerTransportStack(
            RdpbcgrServer rdpbcgrServer,
            RdpcbgrServerTransportConfig transportConfig,
            DecodePacketCallback decodePacketCallback)
        {
            this.rdpbcgrServer = rdpbcgrServer;
            this.config        = transportConfig;
            if (this.config == null)
            {
                throw new System.InvalidCastException("TcpServerTransport needs SocketTransportConfig.");
            }

            this.decoder     = decodePacketCallback;
            this.packetQueue = new QueueManager();

            this.receivingStreams = new Dictionary <Socket, RdpbcgrReceiveThread>();
        }
Example #5
0
        /// <summary>
        /// consturctor.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not StreamConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public RdpbcgrClientTransportStack(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);
            buffer           = new List <byte>();
            this.eventQueue  = new SyncFilterQueue <TransportEvent>();
            this.packetCache = new SyncFilterQueue <StackPacket>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// expect packet from transport.
        /// </summary>
        /// <param name="buffer">
        /// a BytesBuffer object that contains the received data from endpoint.
        /// </param>
        /// <param name="decoder">
        /// a DecodePacketCallback delegate that is used to decode packet from buffer.
        /// </param>
        /// <param name="endpoint">
        /// an object that specifies the endpoint for decoder.<para/>
        /// remember: this endpoint is the identity endpoint of tcp/netbios connection,
        /// that is the remote endpoint of connection.
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="consumedLength">
        /// return an int value that specifies the consumed length.
        /// </param>
        /// <returns>
        /// a StackPacket object that specifies the received packet.
        /// </returns>
        public static StackPacket[] Visit(
            BytesBuffer buffer, DecodePacketCallback decoder, object endpoint,
            TimeSpan timeout, out int consumedLength)
        {
            bool bufferClosed;

            // get all data in buffer, at-least one byte.
            byte[] data = buffer.Read(timeout, BytesBuffer.MaxCount, 0, out bufferClosed);

            // the end time for operation.
            DateTime endTime = DateTime.Now + timeout;

            while (true)
            {
                // decode packets using data in buffer.
                int expectedLength = 0;

                // decode data.
                if (data.Length > 0)
                {
                    StackPacket[] packets = decoder(endpoint, data, out consumedLength, out expectedLength);

                    buffer.Remove(consumedLength);

                    // if packet arrived, add to packet list, and return the first.
                    if (packets != null && packets.Length > 0)
                    {
                        return(packets);
                    }
                }

                // if buffer is closed, no data will come, return null.
                if (bufferClosed)
                {
                    consumedLength = 0;
                    return(null);
                }

                // wait for the next data coming.
                data = buffer.Read(endTime - DateTime.Now, BytesBuffer.MaxCount, data.Length, out bufferClosed);
            }
        }
        /// <summary>
        /// consturctor.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not StreamConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public StreamTransport(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);

            this.buffer      = new BytesBuffer();
            this.eventQueue  = new SyncFilterQueue <TransportEvent>();
            this.packetCache = new SyncFilterQueue <StackPacket>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not SocketTransportConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public UdpClientTransport(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);

            this.eventQueue  = new SyncFilterQueue <TransportEvent>();
            this.buffer      = new SyncFilterQueue <UdpReceivedBytes>();
            this.packetCache = new SyncFilterQueue <IPEndPointStackPacket>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// consturctor.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not StreamConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public StreamTransport(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);

            this.buffer = new BytesBuffer();
            this.eventQueue = new SyncFilterQueue<TransportEvent>();
            this.packetCache = new SyncFilterQueue<StackPacket>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// consturctor.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not SocketTransportConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public TcpServerTransport(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);

            this.decoder = decodePacketCallback;
            this.listeners = new Dictionary<IPEndPoint, TcpServerListener>();
            this.connections = new Dictionary<IPEndPoint, TcpServerConnection>();
            this.eventQueue = new SyncFilterQueue<TransportEvent>();
            this.sequence = new DataSequence();
            this.packetCache = new SyncFilterQueue<IPEndPointStackPacket>();
        }
        /// <summary>
        /// Create a new thread to receive the data from remote host.
        /// </summary>
        /// <param name="packetQueueManager">Store all event packets generated in receiving loop.</param>
        /// <param name="decodePacketCallback">Callback of packet decode.</param>
        /// <param name="stream">The stream used to receive data.</param>
        /// <param name="bufferSize">Buffer size used in receiving data.</param>
        public RdpbcgrReceiveThread(
            object endPoint,
            QueueManager packetQueueManager,
            DecodePacketCallback decodePacketCallback,
            Stream stream,
            int bufferSize,
            RdpbcgrServer rdpbcgrServer)
        {
            if (packetQueueManager == null)
            {
                throw new ArgumentNullException("packetQueueManager");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            // Initialize variable.
            this.endPointIdentity = endPoint;
            this.packetQueue = packetQueueManager;
            this.decoder = decodePacketCallback;
            this.receiveStream = stream;
            this.maxBufferSize = bufferSize;
            this.rdpbcgrServer = rdpbcgrServer;
            this.receivingThread = new Thread((new ThreadStart(ReceiveLoop)));
        }
        /// <summary>
        ///  Constructor. Initialize member variables.
        /// </summary>
        /// <param name="transportConfig">Provides the transport parameters.</param>
        /// <param name="decodePacketCallback">Callback of decoding packet.</param>
        /// <param name="certificate">X509 certificate.</param>
        public RdpbcgrServerTransportStack(
            RdpbcgrServer rdpbcgrServer,
            RdpcbgrServerTransportConfig transportConfig,
            DecodePacketCallback decodePacketCallback,
            X509Certificate2 certificate)
        {
            this.rdpbcgrServer = rdpbcgrServer;
            this.config = transportConfig;
            if (this.config == null)
            {
                throw new System.InvalidCastException("TcpServerTransport needs SocketTransportConfig.");
            }

            this.decoder = decodePacketCallback;
            this.packetQueue = new QueueManager();
            this.listenSock = new Socket(transportConfig.LocalIpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            this.streamType = transportConfig.StreamType;
            IPEndPoint endPoint = new IPEndPoint(config.LocalIpAddress, config.LocalIpPort);
            this.listenSock.Bind(endPoint);
            this.listenSock.Listen(config.MaxConnections);
            this.acceptThread = new Thread(new ThreadStart(AcceptLoop));
            this.receivingStreams = new Dictionary<Socket, RdpbcgrReceiveThread>();
            this.cert = certificate;
        }
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not SocketTransportConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public UdpServerTransport(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);

            this.listeners = new Dictionary<IPEndPoint, UdpServerListener>();
            this.eventQueue = new SyncFilterQueue<TransportEvent>();
            this.packetCache = new SyncFilterQueue<IPEndPointStackPacket>();
            this.buffer = new SyncFilterQueue<UdpReceivedBytes>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// Constructor. To create the instance of transport specified in the transportConfig.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that specifies the transport type and parameters.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// thrown when StackTransportType is invalid.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// thrown when Role is invalid, for transport type is Tcp, it must be Server or Client.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// thrown when Role is invalid, for transport type is Netbios, it must be Server or Client.
        /// </exception>
        public TransportStack(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            switch (transportConfig.Type)
            {
                case StackTransportType.Tcp:

                    if (transportConfig.Role == Role.Client)
                    {
                        this.transport = new TcpClientTransport(transportConfig, decodePacketCallback);
                    }
                    else if (transportConfig.Role == Role.Server)
                    {
                        this.transport = new TcpServerTransport(transportConfig, decodePacketCallback);
                    }
                    else
                    {
                        throw new InvalidOperationException(
                            "Role is invalid, for transport type is Tcp, it must be Server or Client.");
                    }

                    break;

                case StackTransportType.Netbios:

                    if (transportConfig.Role == Role.Client)
                    {
                        this.transport = new NetbiosClientTransport(transportConfig, decodePacketCallback);
                    }
                    else if (transportConfig.Role == Role.Server)
                    {
                        this.transport = new NetbiosServerTransport(transportConfig, decodePacketCallback);
                    }
                    else
                    {
                        throw new InvalidOperationException(
                            "Role is invalid, for transport type is Netbios, it must be Server or Client.");
                    }

                    break;

                case StackTransportType.Stream:

                    this.transport = new StreamTransport(transportConfig, decodePacketCallback);

                    break;

                case StackTransportType.Udp:

                    if (transportConfig.Role == Role.Server)
                    {
                        this.transport = new UdpServerTransport(transportConfig, decodePacketCallback);
                    }
                    // all other role are equals to Client.
                    else
                    {
                        this.transport = new UdpClientTransport(transportConfig, decodePacketCallback);
                    }

                    break;

                default:
                    throw new InvalidOperationException("StackTransportType is invalid.");
            }
        }
        /// <summary>
        /// expect packet from transport.
        /// </summary>
        /// <param name="buffer">
        /// a BytesBuffer object that contains the received data from endpoint.
        /// </param>
        /// <param name="decoder">
        /// a DecodePacketCallback delegate that is used to decode packet from buffer.
        /// </param>
        /// <param name="endpoint">
        /// an object that specifies the endpoint for decoder.<para/>
        /// remember: this endpoint must be the endpoint that is returned to the user,
        /// that is the endpoint return by Connect().
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="packetCache">
        /// a list that contains the stackpackets.
        /// </param>
        /// <returns>
        /// a StackPacket object that specifies the received packet.
        /// </returns>
        public static StackPacket Visit(
            BytesBuffer buffer, DecodePacketCallback decoder, object endpoint,
            TimeSpan timeout, SyncFilterQueue<StackPacket> packetCache)
        {
            // get the packet in packet list.
            if (packetCache.Count > 0)
            {
                return Utility.GetOne<StackPacket>(packetCache, null);
            }

            // the consumed length of decoder.
            int consumedLength = 0;

            // decode packet, return null or at least one packet.
            StackPacket[] packets = ExpectMultiPacketsVisitor.Visit(
                buffer, decoder, endpoint, timeout, out consumedLength);

            // packet is null, buffer is closed, no packet will come.
            if (packets == null)
            {
                return null;
            }

            // if packet arrived, add to packet list, and return the first.
            foreach (StackPacket packet in packets)
            {
                packetCache.Enqueue(packet);
            }

            return Utility.GetOne<StackPacket>(packetCache, null);
        }
        /// <summary>
        /// consturctor.
        /// </summary>
        /// <param name="transportConfig">
        /// a TransportConfig object that contains the config.
        /// </param>
        /// <param name="decodePacketCallback">
        /// a DecodePacketCallback delegate that is used to decode the packet from bytes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not StreamConfig
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when transportConfig is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when decodePacketCallback is null.
        /// </exception>
        public RdpbcgrClientTransportStack(TransportConfig transportConfig, DecodePacketCallback decodePacketCallback)
        {
            if (transportConfig == null)
            {
                throw new ArgumentNullException("transportConfig");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            this.UpdateConfig(transportConfig);
            buffer = new List<byte>();
            this.eventQueue = new SyncFilterQueue<TransportEvent>();
            this.packetCache = new SyncFilterQueue<StackPacket>();

            this.decoder = decodePacketCallback;
        }
        /// <summary>
        /// expect packet from transport.
        /// </summary>
        /// <param name="buffer">
        /// a BytesBuffer object that contains the received data from endpoint.
        /// </param>
        /// <param name="decoder">
        /// a DecodePacketCallback delegate that is used to decode packet from buffer.
        /// </param>
        /// <param name="endpoint">
        /// an object that specifies the endpoint for decoder.<para/>
        /// remember: this endpoint is the identity endpoint of tcp/netbios connection,
        /// that is the remote endpoint of connection.
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="consumedLength">
        /// return an int value that specifies the consumed length.
        /// </param>
        /// <returns>
        /// a StackPacket object that specifies the received packet.
        /// </returns>
        public static StackPacket[] Visit(
            BytesBuffer buffer, DecodePacketCallback decoder, object endpoint,
            TimeSpan timeout, out int consumedLength)
        {
            bool bufferClosed;
            // get all data in buffer, at-least one byte.
            byte[] data = buffer.Read(timeout, BytesBuffer.MaxCount, 0, out bufferClosed);

            // the end time for operation.
            DateTime endTime = DateTime.Now + timeout;

            while (true)
            {
                // decode packets using data in buffer.
                int expectedLength = 0;

                // decode data.
                if (data.Length > 0)
                {
                    StackPacket[] packets = decoder(endpoint, data, out consumedLength, out expectedLength);

                    buffer.Remove(consumedLength);

                    // if packet arrived, add to packet list, and return the first.
                    if (packets != null && packets.Length > 0)
                    {
                        return packets;
                    }
                }

                // if buffer is closed, no data will come, return null.
                if (bufferClosed)
                {
                    consumedLength = 0;
                    return null;
                }

                // wait for the next data coming.
                data = buffer.Read(endTime - DateTime.Now, BytesBuffer.MaxCount, data.Length, out bufferClosed);
            }
        }