Example #1
0
        public void TestResendsAfterLosingAcks()
        {
            Cdp.TryStaticInit(Cdp.MaxPayloadWithIDOverUdp);

            IPEndPoint        serverEndPoint = new IPEndPoint(IPAddress.Loopback, testUdpPort);
            FixedRetryTimeout timeout        = new FixedRetryTimeout(100, 6);

            using (TestServerWrapper server = new TestServerWrapper(serverEndPoint, timeout))
            {
                Cdp.TryStaticInit(Cdp.MaxPayloadWithIDOverUdp);

                //
                //
                //
                UdpConnectedClientTransmitter udpTransmitter    = new UdpConnectedClientTransmitter(serverEndPoint);
                ClumsyTransmitter             clumsyTransmitter = new ClumsyTransmitter(udpTransmitter, Console.Out);
                CdpTransmitter transmitter = new CdpTransmitter(clumsyTransmitter);

                Int64 startTicks = Stopwatch.GetTimestamp();
                Console.WriteLine("[Sender {0} millis] Sending...", (Stopwatch.GetTimestamp() - startTicks).StopwatchTicksAsInt64Milliseconds());

                UInt32 offset;
                Byte[] datagram = transmitter.RequestSendBuffer(10, out offset);
                for (Byte i = 0; i < 10; i++)
                {
                    datagram[offset++] = (Byte)('A' + i);
                }
                clumsyTransmitter.DropAllReceivedDatagramsForTheNext(400);
                transmitter.ControllerSendPayloadWithAck(offset, timeout);
                server.TestSucceeded();
            }
        }
        public void SimpleTestMethod()
        {
            Cdp.TryStaticInit(Cdp.MaxPayloadWithIDOverUdp);

            VirtualDatagramTransmitter transmitter = new VirtualDatagramTransmitter();

            transmitter.Print(Console.Out);


            byte[] sendBuffer = new Byte[] { 0, 1, 2, 3, 4 };
            byte[] receiveBuffer;
            Int32  length;

            //
            // Send Buffer
            //
            transmitter.Send(sendBuffer, 0, (UInt32)sendBuffer.Length);
            Assert.AreEqual(1, transmitter.DatagramsInSendQueue);

            //
            // Receive Buffer
            //
            receiveBuffer = new Byte[sendBuffer.Length];
            length        = transmitter.otherTransmitter.ReceiveNonBlocking(receiveBuffer, 0, (UInt32)receiveBuffer.Length);
            Assert.AreEqual(sendBuffer.Length, length);
            Assert.AreEqual(0, transmitter.DatagramsInSendQueue);
            CdpTest.AssertEqual(sendBuffer, receiveBuffer);

            length = transmitter.otherTransmitter.ReceiveNonBlocking(receiveBuffer, 0, (UInt32)sendBuffer.Length);
            Assert.AreEqual(-1, length);

            //
            // Send the buffer 5 times
            //
            for (int i = 0; i < 5; i++)
            {
                sendBuffer[0] = (Byte)i;
                transmitter.Send(sendBuffer, 0, (UInt32)sendBuffer.Length);
                Assert.AreEqual(i + 1, transmitter.DatagramsInSendQueue);
            }
            transmitter.Print(Console.Out);
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Receiving datagram {0}", i + 1);
                receiveBuffer = new Byte[sendBuffer.Length];
                length        = transmitter.otherTransmitter.ReceiveNonBlocking(receiveBuffer, 0, (UInt32)receiveBuffer.Length);
                Assert.AreEqual(sendBuffer.Length, length);
                Assert.AreEqual(4 - i, transmitter.DatagramsInSendQueue);

                sendBuffer[0] = (Byte)i;
                CdpTest.AssertEqual(sendBuffer, receiveBuffer);
            }

            length = transmitter.otherTransmitter.ReceiveNonBlocking(receiveBuffer, 0, (UInt32)sendBuffer.Length);
            Assert.AreEqual(-1, length);
        }
Example #3
0
        public void TestMethod1()
        {
            Cdp.TryStaticInit(Cdp.MaxPayloadWithIDOverUdp);

            IPEndPoint        serverEndPoint = new IPEndPoint(IPAddress.Loopback, testUdpPort);
            FixedRetryTimeout timeout        = new FixedRetryTimeout(500, 6);

            using (TestServerWrapper server = new TestServerWrapper(serverEndPoint, timeout))
            {
                UdpConnectedClientTransmitter udpTransmitter = new UdpConnectedClientTransmitter(serverEndPoint);
                CdpTransmitter transmitter = new CdpTransmitter(udpTransmitter);


                UInt32 offset;
                Byte[] myMessage;
                Byte[] payloadBuffer;


                //
                // Send and wait for ack
                //
                myMessage = Encoding.UTF8.GetBytes("This should be a normal payload with an immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                Console.WriteLine("[Client] Sending Payload With Ack...");
                transmitter.ControllerSendPayloadWithAck(offset, timeout);

                //
                // Send heartbeat
                //
                Console.WriteLine("[Client] Sending Heartbeat...");
                transmitter.SendHearbeat();

                //
                // Send Random Payload
                //
                myMessage = Encoding.UTF8.GetBytes("This should be a random payload");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                Console.WriteLine("[Client] Sending Random Payload...");
                transmitter.ControllerSendRandomPayload(offset);

                //
                // Send Payload no ack
                //
                myMessage = Encoding.UTF8.GetBytes("This should be the first payload with no immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                Console.WriteLine("[Client] Sending Payload No Ack...");
                transmitter.ControllerSendPayloadNoAck(offset);

                //
                // Send Payload no ack
                //
                myMessage = Encoding.UTF8.GetBytes("This should be the second payload with no immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                Console.WriteLine("[Client] Sending Payload No Ack...");
                transmitter.ControllerSendPayloadNoAck(offset);

                //
                // Send and wait for ack
                //
                myMessage = Encoding.UTF8.GetBytes("This should be a normal payload with an immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                Console.WriteLine("[Client] Sending Payload With Ack...");
                transmitter.ControllerSendPayloadWithAck(offset, timeout);

                //
                // Send Halt
                //
                Console.WriteLine("[Client] Sending Halt...");
                transmitter.SendHaltNoPayload();

                server.TestSucceeded();
                Console.WriteLine("[Client] Done (Success)");
            }
        }
Example #4
0
        //
        // This function implements an algorithm in the CDP protocol
        // specification. See CDP documentation to see the pseudocode for this function.
        //
        // Returns true to close the client
        //
        public Boolean Datagram(Byte[] datagram, Int32 offset, Int32 length)
        {
            /*
             * Console.WriteLine("[CdpDebug] Got Datagram {0} Bytes: {1}",
             *  length, (length <= 0) ? "<null>" : (length < 10) ? BitConverter.ToString(datagram, offset, length) :
             *  BitConverter.ToString(datagram, offset, 10) + "...");
             */


            if (length <= 0)
            {
                return(false);            // just a heartbeat
            }
            Byte flagValue = (Byte)(datagram[offset] >> 4);

            //
            // Check if it is a halt or an out of order datagram
            //
            if (flagValue > 7)
            {
                if (flagValue == (Byte)CdpFlagValue.Halt)
                {
                    serverHandler.Halt();
                    return(true); // true to close client
                }
                if (flagValue == (Byte)CdpFlagValue.Resend)
                {
                    throw new NotImplementedException();
                }
                // The packet is a handler packet, so it should be ignored
                return(false);
            }

            //
            // Check if it contains a payload with an id
            //
            if (flagValue < 6)
            {
                if (length < 2)
                {
                    // The datagram is not valid CDP, halt
                    Console.WriteLine("[CdpDebug] Received Invalid CDP from client, because it has a flag value of {0}, but the datagram is not long enough for the id", flagValue);
                    transmitter.SendHaltNoPayload();
                    serverHandler.Halt();
                    return(true);
                }

                UInt32 payloadID = (UInt32)((0xF00 & (datagram[offset] << 8)) | (0xFF & datagram[offset + 1]));

                while (true)
                {
                    Int32 payloadDiff = Cdp.PayloadDiff(payloadID, transmitter.nextPayloadID);
                    if (payloadDiff == 0)
                    {
                        break;
                    }

                    // Check if it's a resend
                    if (payloadDiff == Cdp.MaxPayloadID)
                    {
                        if (flagValue < 4 && ((flagValue & (Byte)CdpFlagValueFlag.ImmediateAck) != 0))
                        {
                            Console.WriteLine("[CdpDebug] Got a resend of payload {0}. The payload requested an ACK but the ACK must have been lost.", payloadID);
                            // Resend the ack
                            transmitter.HandlerSendHeader((Byte)CdpFlagValue.Ack, payloadID);
                        }
                    }

                    if (payloadDiff >= 0x800)
                    {
                        // The packet is a resend so ignore it
                        Console.WriteLine("[CdpDebug] Received resend of payload id {0}", payloadID);
                        return(false);
                    }

                    //throw new NotImplementedException(String.Format("Received payload id of {0} but the diff is {1} so it is out of order. Out of order packets are not yet implemented",
                    //    payloadID, payloadDiff));

                    // Request a resend
                    transmitter.HandlerSendHeader((Byte)CdpFlagValue.Resend, transmitter.nextPayloadID);
                    return(false);
                }

                // Update last payload id received
                transmitter.nextPayloadID++;

                //
                // If it's not a close or halt with payload, send immediate ack if requested
                //
                if (flagValue < 4 && ((flagValue & (Byte)CdpFlagValueFlag.ImmediateAck) != 0))
                {
                    Console.WriteLine("[CdpDebug] (FlagValue={0}) Sending Ack of payload id {1}", flagValue, payloadID);
                    // Ack the payload
                    transmitter.HandlerSendHeader((Byte)CdpFlagValue.Ack, payloadID);
                }

                // Handle the payload
                Boolean closeClient = serverHandler.Payload(datagram, offset + 2, length - 2);
                if (closeClient)
                {
                    // close the connection
                    transmitter.SendHaltNoPayload();
                    serverHandler.Halt();
                    return(true); // don't keep client alive
                }

                if (flagValue >= 4)     // Either Close or Halt
                {
                    if (flagValue == 5) // It was a close
                    {
                        Boolean acknowledgeClose = serverHandler.Close();
                        if (acknowledgeClose)
                        {
                            throw new NotImplementedException();
                        }
                        else
                        {
                            transmitter.SendHaltNoPayload();
                        }
                    }

                    serverHandler.Halt();
                    return(true);
                }

                if ((flagValue & (Byte)CdpFlagValueFlag.GiveControl) != 0)
                {
                    Int32   sendBufferOffsetLimit;
                    Boolean requestImmediateAck;
                    serverHandler.GotControl(null, out sendBufferOffsetLimit, out requestImmediateAck);
                }

                return(false);
            }
            else if (flagValue == (Byte)CdpFlagValue.RandomPayload)
            {
                return(serverHandler.RandomPayload(datagram, 1, length - 1));
            }
            else
            {
                // The datagram is not valid CDP, halt
                Console.WriteLine("[CdpDebug] Received Invalid CDP from client, unrecognized flag value of {0}", flagValue);
                transmitter.SendHaltNoPayload();
                serverHandler.Halt();
                return(true);
            }
        }
Example #5
0
 public void Run(ICdpServer server, Byte[] maxDatagramBuffer, ICdpTimeout timeout)
 {
     Cdp.UdpServerLoop(server, udpSocket, endPoint, maxDatagramBuffer, timeout);
 }
Example #6
0
        static Int32 Main(string[] args)
        {
            CdpCatOptions optionsParser = new CdpCatOptions();

            if (args.Length <= 0)
            {
                optionsParser.PrintUsage();
                return(-1);
            }

            List <String> nonOptionArgs = optionsParser.Parse(args);

            Cdp.StaticInit(optionsParser.maxPayload.ArgValue);

            ICdpTimeout timeout = new MyCdpTimeout();

            if (optionsParser.listenPort.set)
            {
                IPEndPoint  localEndPoint = new IPEndPoint(IPAddress.Any, optionsParser.listenPort.ArgValue);
                MyCdpServer cdpServer     = new MyCdpServer();
                Socket      udpSocket     = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                Cdp.UdpServerLoop(cdpServer, udpSocket, localEndPoint, new Byte[optionsParser.maxPayload.ArgValue], timeout);
                return(-1);
            }
            else
            {
                if (nonOptionArgs.Count < 2)
                {
                    Console.WriteLine("Missing command line arguments");
                    optionsParser.PrintUsage();
                    return(-1);
                }

                UInt16   port           = UInt16.Parse(nonOptionArgs[1]);
                EndPoint serverEndPoint = new IPEndPoint(EndPoints.ParseIPOrResolveHost(nonOptionArgs[0], DnsPriority.IPv4ThenIPv6), port);

                UdpConnectedClientTransmitter udpTransmitter = new UdpConnectedClientTransmitter(serverEndPoint);
                CdpTransmitter transmitter = new CdpTransmitter(udpTransmitter);


                UInt32 offset;
                Byte[] myMessage;
                Byte[] payloadBuffer;



                transmitter.SendHearbeat();



                myMessage = Encoding.UTF8.GetBytes("This should be a random payload");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                transmitter.ControllerSendRandomPayload(offset + (UInt32)myMessage.Length);



                myMessage = Encoding.UTF8.GetBytes("This should be the first payload with no immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, (UInt32)myMessage.Length);
                transmitter.ControllerSendPayloadNoAck(offset + (UInt32)myMessage.Length);

                myMessage = Encoding.UTF8.GetBytes("This should be the second payload with no immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, (UInt32)myMessage.Length);
                transmitter.ControllerSendPayloadNoAck(offset + (UInt32)myMessage.Length);


                //
                // Send and wait for ack
                //
                myMessage = Encoding.UTF8.GetBytes("This should be a normal payload with an immediate ack");

                payloadBuffer = transmitter.RequestSendBuffer((UInt32)myMessage.Length, out offset);
                Array.Copy(myMessage, 0, payloadBuffer, offset, myMessage.Length);
                offset += (UInt32)myMessage.Length;
                transmitter.ControllerSendPayloadWithAck(offset, timeout);



                transmitter.SendHaltNoPayload();


                return(0);
            }
        }