Esempio n. 1
0
            public TestServerWrapper(IPEndPoint serverEndPoint, ICdpTimeout timeout)
            {
                this.success = false;
                this.server  = null;

                CdpServerForTests cdpServer = new CdpServerForTests();

                server = new CdpServerOverUdp(serverEndPoint);

                new Thread(() =>
                {
                    try
                    {
                        server.Run(cdpServer, new Byte[256], timeout);
                    }
                    catch (Exception e)
                    {
                        if (!success)
                        {
                            Console.WriteLine("[Server] '{0}': {1}", e.GetType().Name, e);
                        }
                    }
                    finally
                    {
                        Console.WriteLine("[Server] Stopped");
                    }
                }).Start();
                Thread.Sleep(100); // wait for server to start
            }
Esempio n. 2
0
        //Int32 lastPayloadIDReceived;

        public CdpServerDatagramHandler(CdpTransmitter transmitter,
                                        ICdpServerHandler serverHandler, ICdpTimeout timeout)
        {
            this.transmitter   = transmitter;
            this.serverHandler = serverHandler;
            this.timeout       = timeout;

            //this.lastPayloadIDReceived = Cdp.MaxPayloadID;
        }
Esempio n. 3
0
 public void Run(ICdpServer server, Byte[] maxDatagramBuffer, ICdpTimeout timeout)
 {
     Cdp.UdpServerLoop(server, udpSocket, endPoint, maxDatagramBuffer, timeout);
 }
Esempio n. 4
0
        public void ControllerSendPayloadWithAck(UInt32 offsetLimit, ICdpTimeout timeout)
        {
            // 1. Check for acks/resends/halts


            Byte[] bufferToSend = GetRequestedBuffer(offsetLimit);

            try
            {
                // Cdp Header
                UInt32 payloadID = nextPayloadID++;
                bufferToSend[0] = (Byte)(((Byte)CdpFlagValue.PayloadWithAck << 4) |
                                         (0x0F & (payloadID >> 8)));
                bufferToSend[1] = (Byte)payloadID;

                //
                // Send the datagram
                //
                connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit);

                Int64 stopwatchTicksAfterSend = Stopwatch.GetTimestamp();

                Int32 timeoutMillis = timeout.WaitForAckInitialRetryTimeout(averageLatency);
                if (timeoutMillis < 0)
                {
                    throw new InvalidOperationException(String.Format(
                                                            "The ICdpTimeout class '{0}' returned negative ({1}) when calling WaitForAckInitialTimeout({2})",
                                                            timeout.GetType().Name, timeoutMillis, averageLatency));
                }

                Int32 retries = 0;

                // Keep resending the datagram until a header is recevied or timeout is reached
                while (true)
                {
                    Console.WriteLine("Send Retry {0}", retries);
                    Int32 bytesRead = connectedDatagramTransmitter.ReceiveBlocking(headerBuffer, 0, 2, timeoutMillis);

                    if (bytesRead < 0)
                    {
                        Int32 elapsedMillis = (Stopwatch.GetTimestamp() - stopwatchTicksAfterSend).StopwatchTicksAsInt32Milliseconds();
                        timeoutMillis = timeout.WaitForAckRetryOrTimeout(retries, averageLatency, elapsedMillis, timeoutMillis);
                        if (timeoutMillis <= 0)
                        {
                            throw new TimeoutException(String.Format("Timed out waiting for ack: {0} retries {1} milliseconds elapsed", retries, elapsedMillis));
                        }

                        // Retry sending the packet
                        connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit);
                        retries++;
                        continue;
                    }

                    //
                    // Check the datagram
                    //
                    if (bytesRead == 0)
                    {
                        // It's just a heart beat packet
                    }
                    else
                    {
                        Byte   receivedFlagValue = (Byte)(headerBuffer[0] >> 4);
                        UInt32 receivedPayloadID = (UInt32)((0xF00 & (headerBuffer[0] << 8)) | (0xFF & headerBuffer[1]));
                        if (receivedFlagValue == (Byte)CdpFlagValue.Ack)
                        {
                            if (receivedPayloadID == payloadID)
                            {
                                Console.WriteLine("[CdpDebug] Received ACK for payload id {0}", payloadID);
                                break;
                            }
                            Console.WriteLine("[CdpDebug] Got an ack for an old payload id {0}?", receivedPayloadID);
                        }
                        else if (receivedFlagValue == (Byte)CdpFlagValue.Halt)
                        {
                            throw new CdpBadHaltException();
                        }
                        else if (receivedFlagValue == (Byte)CdpFlagValue.Resend)
                        {
                            if (receivedPayloadID <= payloadID)
                            {
                                UInt32 index = datagramQueue.PayloadIDToIndex(receivedPayloadID);
                                if (index >= 0)
                                {
                                    if (receivedPayloadID < payloadID)
                                    {
                                        do
                                        {
                                            Console.WriteLine("[Debug] Queue Index {0} Payload ID {1}", index, receivedPayloadID + index);
                                            CdpBufferPoolDatagram datagram = datagramQueue.queue[index];
                                            connectedDatagramTransmitter.Send(datagram.datagram, 0, datagram.length);
                                            index++;
                                        } while (receivedPayloadID + index < payloadID);
                                    }
                                    connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit);
                                }
                            }
                        }
                        else
                        {
                            Console.WriteLine("Unknown flag value {0} from '{1}' (Maybe I should throw an exception? TBD)",
                                              receivedFlagValue, connectedDatagramTransmitter.RemoteEndPoint);
                        }
                    }

                    //
                    // Get next timeout
                    //
                    {
                        Int32 elapsedMillis = (Stopwatch.GetTimestamp() - stopwatchTicksAfterSend).StopwatchTicksAsInt32Milliseconds();
                        timeoutMillis = timeout.WaitForAckRetryOrTimeout(retries, averageLatency, elapsedMillis, timeoutMillis);
                        if (timeoutMillis <= 0)
                        {
                            throw new TimeoutException(String.Format("Timed out waiting for ack: {0} retries {1} milliseconds elapsed", retries, elapsedMillis));
                        }
                    }
                }

                datagramQueue.EmptyAndFree(); // free the queue because everything has been acked
            }
            finally
            {
                Cdp.BufferPool.FreeBuffer(bufferToSend);
            }
        }
Esempio n. 5
0
        public static void UdpServerLoop(ICdpServer server, Socket udpSocket, EndPoint listenEndPoint, Byte[] maxDatagramBuffer, ICdpTimeout timeout)
        {
            Dictionary <EndPoint, CdpServerDatagramHandler> endPointToHandler =
                new Dictionary <EndPoint, CdpServerDatagramHandler>();

            //Socket udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            udpSocket.Bind(listenEndPoint);

            try
            {
                while (true)
                {
                    EndPoint from = listenEndPoint;
                    int      bytesRead;
                    try
                    {
                        bytesRead = udpSocket.ReceiveFrom(maxDatagramBuffer, ref from);
                    }
                    catch (SocketException e)
                    {
                        Boolean stopServerGracefully = server.SocketException(e);
                        if (stopServerGracefully)
                        {
                            throw new NotImplementedException("Stop server gracefully not implemented");
                        }
                        continue;
                    }

                    if (bytesRead <= 0)
                    {
                        // it's just a heartbeat
                        Console.WriteLine("[CdpDebug] Got a heartbeat from '{0}'", from);
                        continue;
                    }

                    CdpServerDatagramHandler handler;

                    //
                    // Handle new connection
                    //
                    if (!endPointToHandler.TryGetValue(from, out handler))
                    {
                        CdpTransmitter transmitter = new CdpTransmitter(new UdpConnectedServerTransmitter(udpSocket, from));

                        ICdpServerHandler serverHandler;
                        Int32             maxSendBeforeAck;
                        Boolean           refuseConnection = server.NewConnection(transmitter, out serverHandler, out maxSendBeforeAck);

                        if (refuseConnection)
                        {
                            handler.Closed();
                            server.ConnectionClosed(from);
                            throw new NotImplementedException("Refusing connection is not yet implemented");
                        }

                        if (serverHandler == null)
                        {
                            handler.Closed();
                            server.ConnectionClosed(from);
                            throw new InvalidOperationException("You provided a null payload handler");
                        }

                        handler = new CdpServerDatagramHandler(transmitter, serverHandler, timeout);
                        endPointToHandler.Add(from, handler);
                    }

                    Boolean closeClient = handler.Datagram(maxDatagramBuffer, 0, bytesRead);
                    if (closeClient)
                    {
                        handler.Closed();
                        server.ConnectionClosed(from);
                        endPointToHandler.Remove(from);
                    }
                }
            }
            finally
            {
                if (udpSocket != null)
                {
                    udpSocket.Close();
                }
            }
        }