public void ClientSocketReceivedPacketCallback(TCPCopycatPacket packet, IPEndPoint sender)
        {
            Console.WriteLine("Received Packet numbered: " + packet.header.sequenceNumber.ToString());

            if (!packetReceived[GetClientSocketFromEndpoint(sender)].Contains(packet.header.sequenceNumber))
            {
                if (packet.header.FIN == 1)
                {
                    Console.WriteLine("Packet FIN received");
                }
                filePacketList[GetClientSocketFromEndpoint(sender)].Add(packet);
                packetReceived[GetClientSocketFromEndpoint(sender)].Add(packet.header.sequenceNumber);
            }

            packet.header.acknowledgeNumber = packet.header.sequenceNumber + 1;
            TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);

            /*
             * if (packet.header.acknowledgeNumber == 30)
             * {
             *  Console.WriteLine("********** SENDING MULTIPLE TIME SAME PACKET *************");
             *  latency(250, 1251);
             *  TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
             *  latency(250, 1251);
             *  TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
             *  latency(250, 1251);
             *  TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
             * }*/
            /*
             * if (packet.header.acknowledgeNumber != 28)
             * {
             *  TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
             * }
             * if (packet.header.acknowledgeNumber == 31)
             * {
             *  Console.WriteLine("*** GoingTo send packet 30 ack ***");
             *  Thread.Sleep(10000);
             *  packet.header.acknowledgeNumber = 28;
             *  TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
             *  Console.WriteLine("*** SENT PACKET ***");
             * }
             */
            if (packet.header.FIN == 1)
            {
                filePacketList[GetClientSocketFromEndpoint(sender)].Sort(delegate(TCPCopycatPacket a, TCPCopycatPacket b)
                {
                    if (a.header.sequenceNumber < b.header.sequenceNumber)
                    {
                        return(-1);
                    }
                    return(1);
                });

                TCPCopycatPacketManager.TCPCopycatPacketArrayToFile(@"./" + sender.Port.ToString(), filePacketList[GetClientSocketFromEndpoint(sender)].ToArray());
            }
        }
        private void registerPacket(TCPCopycatPacket packet, TCPCopycatReceiveMessageCallback lambda, int waitTime)
        {
            if (waitTime < 0)
            {
                throw new Exception("waitTime must be positive");
            }

            //Console.WriteLine("registering packet: " + packet.header.sequenceNumber);
            if (dictionaryRegisteredPacket.ContainsKey(packet.header.sequenceNumber + 1))
            {
                dictionaryRegisteredPacket[packet.header.sequenceNumber + 1] = lambda;
            }
            else
            {
                dictionaryRegisteredPacket.Add(packet.header.sequenceNumber + 1, lambda);
            }
            //Console.WriteLine(dictionaryRegisteredPacket.Count.ToString() + " packets registered");


            setPacketResponse(packet.header.sequenceNumber + 1, TCPCopyCatController.responseCode.NONE);

            ElapsedEventHandler timerCallbackLambda = delegate(object state, System.Timers.ElapsedEventArgs e)
            {
                TaskTimer        t                 = (TaskTimer)state;
                TCPCopycatPacket packetToSend      = t.packetToSend;
                TCPCopycatReceiveMessageCallback l = t.lambda;
                int w = t.waitTime;
                t.Dispose();
                if (dictionaryRegisteredPacketResponse[packetToSend.header.sequenceNumber + 1] == TCPCopyCatController.responseCode.OK) //unregister timer is called before the timer is even initialized
                {
                    return;
                }
                Console.WriteLine("packet: " + packetToSend.header.sequenceNumber.ToString() + " lost");
                unregisterPacket(packetToSend.header.sequenceNumber + 1);
                setPacketResponse(packetToSend.header.sequenceNumber + 1, TCPCopyCatController.responseCode.NONE);
                TCPCopyCatController.sendMessageToEndPoint(socket, serverEndpoint, packetToSend);
                registerPacket(packetToSend, l, w);
            };


            TaskTimer timer = new TaskTimer();

            timer.Interval  = waitTime;                                                   // set the interval as 10000 ms
            timer.Elapsed  += new System.Timers.ElapsedEventHandler(timerCallbackLambda); // set the event to execute
            timer.AutoReset = false;                                                      // false: only execute once
            timer.Enabled   = true;                                                       // to decide if execute the event of timer specified

            timer.packetToSend = packet;
            timer.lambda       = lambda;
            timer.waitTime     = waitTime;


            registerTimer(packet.header.sequenceNumber + 1, timer);
        }
        public void initializeServer(int port)
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);

            serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            serversocket.Bind(endpoint);
            clientSockets = new Dictionary <IPEndPoint, Socket>();
            Console.WriteLine("Server Initialized");

            TCPCopyCatController.startListenOnSocketAsync(serversocket, ServerReceivedPacketCallback);
        }
        public async Task <TCPCopyCatController.responseCode> connectToServer(IPEndPoint serverEndpoint)
        {
            const int connectionSequenceNumber = 0;

            if (socket == null)
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            }
            else if (socket.IsBound)
            {
                return(await getPacketResponse(connectionSequenceNumber + 1));
            }
            TCPCopyCatController.startListenOnSocketAsync(socket, onPacketReceive);

            IPEndPoint test = new IPEndPoint(IPAddress.Any, 0);

            socket.Bind(test);

            this.serverEndpoint = serverEndpoint;

            TCPCopycatPacket.TCPCopycatHeader header = new TCPCopycatPacket.TCPCopycatHeader();

            header.SYN            = 1;
            header.sequenceNumber = connectionSequenceNumber;
            header.ACK            = 0;
            header.dataLenght     = 0;

            TCPCopycatPacket connectionPacket = new TCPCopycatPacket(header, new byte[1]);

            TCPCopycatReceiveMessageCallback receivedMessageCallbackLambda = delegate(TCPCopycatPacket packet, IPEndPoint sender)
            {
                if (packet.header.SYN == 1 && packet.header.acknowledgeNumber == (connectionSequenceNumber + 1))
                {
                    this.serverEndpoint = sender;
                    return(TCPCopyCatController.responseCode.OK);
                }
                return(TCPCopyCatController.responseCode.UNKNOWN_ERROR);
            };



            if (!TCPCopyCatController.sendMessageToEndPoint(socket, serverEndpoint, connectionPacket))
            {
                registerPacket(connectionPacket, receivedMessageCallbackLambda, 1000);
                return(await getPacketResponse(connectionSequenceNumber + 1));
            }
            else
            {
                return(TCPCopyCatController.responseCode.BAD_REQUEST);
            }
        }
        public void ServerReceivedPacketCallback(TCPCopycatPacket packet, IPEndPoint sender)
        {
            Console.WriteLine("Received new connection from " + sender.Address + " port: " + sender.Port);

            clientSockets.Add(sender, new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp));
            IPEndPoint qwe = new IPEndPoint(IPAddress.Any, 0);

            clientSockets[sender].Bind(qwe);
            packetReceived.Add(GetClientSocketFromEndpoint(sender), new HashSet <int>());
            filePacketList.Add(GetClientSocketFromEndpoint(sender), new List <TCPCopycatPacket>());
            Console.WriteLine("Client socket listening on port: " + sender.Port.ToString());
            TCPCopyCatController.startListenOnSocketAsync(GetClientSocketFromEndpoint(sender), ClientSocketReceivedPacketCallback);
            packet.header.acknowledgeNumber = packet.header.sequenceNumber + 1;
            TCPCopyCatController.sendMessageToEndPoint(GetClientSocketFromEndpoint(sender), sender, packet);
        }
        public void sendFilePacket(TCPCopycatPacket packet)
        {
            if (packet == null)
            {
                return;
            }

            if (packet.header.sequenceNumber == filePackets[filePackets.Length - 1].header.sequenceNumber)
            {
                packet.header.FIN = 1;
            }

            packet.header.sequenceNumber += sequenceNumberOffset;

            TCPCopycatReceiveMessageCallback receivedMessageCallbackLambda = delegate(TCPCopycatPacket _packet, IPEndPoint sender)
            {
                unregisterPacket(_packet.header.acknowledgeNumber);
                setPacketResponse(_packet.header.acknowledgeNumber, TCPCopyCatController.responseCode.OK);

                // this ensure we only send 10 files at a time and also respect the selective repeat structure
                if (_packet.header.sequenceNumber < windowLowerbound)
                {
                    Console.WriteLine("************** Already received packet " + (_packet.header.sequenceNumber).ToString() + " ***********");
                }
                else if (_packet.header.sequenceNumber > windowLowerbound)
                {
                    Console.WriteLine("************** Not in order packet received " + (_packet.header.sequenceNumber).ToString() + " ***********");
                }
                else if (_packet.header.sequenceNumber == windowLowerbound)
                {
                    Console.WriteLine("************** In order " + (_packet.header.sequenceNumber).ToString() + " ***********");
                }
                translateWindow();


                return(TCPCopyCatController.responseCode.OK);
            };

            //Console.WriteLine("Sending file to port: " + serverEndpoint.Port.ToString());
            if (!TCPCopyCatController.sendMessageToEndPoint(socket, serverEndpoint, packet))
            {
                registerPacket(packet, receivedMessageCallbackLambda, 2500);
            }
        }