Пример #1
0
        //pripoji Clienta na adresu receivera
        private void Connect(uint length, uint count, IPEndPoint ip)
        {
            _target         = ip;
            MaxPackets      = Math.Min(MaxPackets, count);
            MaxPacketLength = Math.Min(MaxPacketLength, length);

            _stop_and_wait = MaxPackets == 1;


            byte[] message = MessageConstructor.GetHandshake(MaxPacketLength, MaxPackets, MaxSpeed);
            Client.Connect(ip);
            Client.Send(message, message.Length);

            _is_connected = true;
            Connected?.Invoke(this, new EventArgs());
        }
Пример #2
0
        //Dictionary<uint, DataPacket> received_packets;
        //DataPacket[] packets;
        private void ReceivePacket(DataPacket packet)
        {
            ////je to packet, ktery ocekavam
            ///
            if (ReceivedPackets[packet.Number] is null)
            {
                ReceivedPackets[packet.Number] = packet;
                UpdateAwaitedNum();
            }
            else
            {
                //return;
            }


            WriteStatus(AwaitedPacketNum, TotalPacketCount);

            byte[] resp = MessageConstructor.GetDataReceived(packet.Number, AwaitedPacketNum);
            Client.Send(resp, resp.Length);
        }
Пример #3
0
        private void OnClientDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!MessageConstructor.ValidateMessage(e.Data))
            {
                if (StopAndWait)
                {
                    byte[] msg = MessageConstructor.GetDataReceived(uint.MinValue, uint.MaxValue);
                    Client.Send(msg, msg.Length);
                }

                return;
            }

            if (MessageConstructor.IsHandshake(e.Data))
            {
                Connect(BitConverter.ToUInt32(e.Data, 1), BitConverter.ToUInt32(e.Data, 1 + sizeof(int)), e.EndPoint);
                return;
            }

            if (IsTransfering && MessageConstructor.IsFileData(e.Data))
            {
                ReceivePacket(MessageConstructor.GetPacket(e.Data));
                return;
            }

            if (MessageConstructor.IsFileMeta(e.Data))
            {
                TotalPacketCount = BitConverter.ToUInt32(e.Data, 1 + sizeof(long));


                string fn = Encoding.ASCII.GetString(e.Data, 1 + sizeof(long) + sizeof(uint), e.Data.Length - 1 - sizeof(long) - sizeof(uint) - sizeof(uint));
                PrepareFile(fn);

                ReceivedPackets = new DataPacket[TotalPacketCount];

                Console.WriteLine($"Receiving file '{fn}', total of {TotalPacketCount} packets.");
                WriteStatus(0, TotalPacketCount, false);
                Client.Send(e.Data, e.Data.Length);

                //Client.ErrorRate = 0.001;
                //Client.DropRate = 0.01;
            }

            if (IsTransfering && MessageConstructor.IsFileEnd(e.Data))
            {
                WriteFile();

                uint hash = BitConverter.ToUInt32(e.Data, 1);

                uint computed = MessageConstructor.GetFileHash(FileName);

                if (hash == computed)
                {
                    FileReceived?.Invoke(this, new FileReceivedEventArgs()
                    {
                        FileName = FileName
                    });
                    _is_transfering = false;
                }
                else
                {
                    Console.WriteLine("Something is wrong, received different hash.");
                    _is_transfering = false;
                }
            }
        }
Пример #4
0
        //uint last_ack = 0;
        public void SendFile(string path)
        {
            DeliveredPacketCount = 0;
            _is_transfering      = true;
            string file_name = Path.GetFileName(path);

            int buffer_size = (int)MaxPacketLength - DataPacket.MiscLength;

            // poslu FileMeta msg a pockam na odpoved - Handshake se stejnymi hodnotami
            FileInfo finfo    = new FileInfo(path);
            uint     pack_cnt = (uint)(finfo.Length / buffer_size + (finfo.Length % buffer_size > 0 ? 1 : 0));

            //zkratit file_name, aby se veslo do maximalni delky packetu
            if (file_name.Length > (MaxPacketLength - sizeof(byte) - sizeof(long) - sizeof(int) - sizeof(uint)))
            {
                file_name = file_name.Substring((int)(MaxPacketLength - sizeof(byte) - sizeof(long) - sizeof(int) - sizeof(uint)));
            }

            byte[] msg = MessageConstructor.GetFileMeta(finfo.Length, pack_cnt, file_name);
            Client.Send(msg, msg.Length, Target);

            while (meta_response == null)
            {
            }

            if (!Extensions.AreSameArrays(msg, meta_response))
            {
                meta_response = null;
                throw new Exception("Invalid FileMeta response");
            }

            meta_response = null;

            // kdykoliv to bude mozne, tak budu posilat packety...
            // array - vsechny aktualni nepotvrzene packety
            uint packet_num = 0;

            // v tomto HashSetu jsou indexy packetu, ktere jsou potvrzene, tudiz je mozne je pouzit
            AckPackets = new HashSet <int>();
            for (int i = 0; i < MaxPackets; ++i)
            {
                AckPackets.Add(i);
            }


            //int buffer_size = (int)MaxPacketLength - //packet length
            //                  1 -               //packet type
            //                  sizeof(uint) -     //number of packet
            //                  sizeof(uint) -     //data length
            //                  sizeof(uint);     //CRC


            //indkuje, ze je potreba zrusit nejaky cyclus, pouziti ruzne
            bool break_cycle;

            WriteStatus(DeliveredPacketCount, pack_cnt, false);

            Client.ErrorRate = 0.1;
            Client.DropRate  = 0.1;

            using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read)))
            {
                byte[] read_buffer = new byte[buffer_size];
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    int act_count = reader.Read(read_buffer, 0, buffer_size);

                    if (act_count < 0)
                    {
                    }

                    // cekam na volny packet
                    int idx;
                    while (true)
                    {
                        PacketsMutex.WaitOne();
                        break_cycle = AckPackets.Count > 0;
                        PacketsMutex.ReleaseMutex();
                        if (break_cycle)
                        {
                            break;
                        }
                        Thread.Sleep(20);
                    }

                    PacketsMutex.WaitOne();
                    idx = AckPackets.Pop();
                    PacketsMutex.ReleaseMutex();

                    //Nastvaim hodnoty volneho packetu
                    // nemelo by byt potreba nastavovat PacketMutext, protoze jina vlakna by v tento moment nemela pristupovat k datum ktera chci upravovat
                    //PacketsMutex.WaitOne();

                    Packets[idx].Data     = MessageConstructor.GetFileData(packet_num, read_buffer, (uint)act_count);
                    Packets[idx].Number   = packet_num;
                    Packets[idx].AckCount = 0;

                    //PacketsMutex.ReleaseMutex();

                    Client.SendPacket(Packets[idx], Target);

                    //zvysuji cislo packetu
                    packet_num++;

                    WriteStatus(DeliveredPacketCount, pack_cnt);
                }
            }

            //v tento moment jsou vsechnz packety dorucene ci na ceste, cekam na ack vsech prave posilanych

            while (true)
            {
                PacketsMutex.WaitOne();
                // tedy vsechny packety jsou volne
                break_cycle = AckPackets.Count >= MaxPackets;
                PacketsMutex.ReleaseMutex();
                WriteStatus(DeliveredPacketCount, pack_cnt);
                if (break_cycle)
                {
                    break;
                }
                Thread.Sleep(20);
            }

            // poslu FileEnd msg
            //TODO: vypocet File hash
            byte[] file_end = MessageConstructor.GetFileEnd(MessageConstructor.GetFileHash(file_name));
            Client.Send(file_end, file_end.Length, Target);

            // jine vlakno prijme reakci na file_end message a pokud to nebude uspokojiva odpoved, zopakuje zaslani...
        }
Пример #5
0
        //called if there are new data
        private void OnClientDataReceived(object sender, DataReceivedEventArgs e)
        {
            //neplatne zpravy zahazujeme
            if (!MessageConstructor.ValidateMessage(e.Data))
            {
                return;
            }

            if (MessageConstructor.IsHandshake(e.Data))
            {
                handshake_response = e.Data;
                return;
            }

            if (MessageConstructor.IsDataReceived(e.Data))
            {
                uint rc_packet_num = BitConverter.ToUInt32(e.Data, 1);
                uint aw_packet_num = BitConverter.ToUInt32(e.Data, 1 + sizeof(uint));

                if (StopAndWait && rc_packet_num == UInt32.MinValue && aw_packet_num == UInt32.MaxValue)
                {
                    // rezim stop and go => pouze jeden packet na ceste a prijemce prijal chybnou zpravu
                    // posli znova packet
                    Client.SendPacket(Packets[0], Target);
                    return;
                }

                PacketsMutex.WaitOne();
                for (int i = 0; i < MaxPackets; ++i)
                {
                    if (Packets[i].AckCount == -1)
                    {
                        continue;
                    }
                    //if (Packets[i].Number == packet_num)
                    //{
                    //    is_pending = true;
                    //    Packets[i].OnReceive();
                    //    packet_num--;
                    //    AckPackets.Add(i);
                    //}

                    if (Packets[i].Number == rc_packet_num)
                    {
                        Packets[i].OnReceive();
                        //rc_packet_num--;
                        AckPackets.Add(i);
                        DeliveredPacketCount++;
                    }
                    if (Packets[i].Number == aw_packet_num)
                    {
                        Packets[i].AckCount++;
                        if (Packets[i].AckCount >= 3)
                        {
                            Client.SendPacket(Packets[i], Target);
                        }
                    }
                }

                PacketsMutex.ReleaseMutex();
                //Console.WriteLine($"Received ACK of {packet_num}");
                return;
            }

            if (MessageConstructor.IsFileMeta(e.Data))
            {
                meta_response = e.Data;
                return;
            }
        }
Пример #6
0
        private void Connect()
        {
            _is_connected = false;
            try
            {
                //Client.Connect(Target);
                // navrhnu svoje hodnoty delky packetu a poctu packetu
                byte[] message = MessageConstructor.GetHandshake(MaxPacketLength, MaxPackets);
                Client.Send(message, message.Length, Target);

                DateTime milis = DateTime.Now;
                // handske timeout
                //TODO pridat nejaky timeout na handshake
                while (handshake_response == null || (DateTime.Now.Ticks - milis.Ticks) < HandshakeTimeout)
                {
                }
                if (handshake_response == null)
                {
                    throw new Exception("Handshake Timeout");
                }

                //if (MessageConstructor.ValidateMessage(handshake_response) &&  MessageConstructor.IsHandshake(handshake_response))
                //{
                //    // bud prijme moje => vrati mnou poslane hodnoty, nebo je snizi => Math.Min(...)
                //    MaxPacketLength = Math.Min(MaxPacketLength, BitConverter.ToInt32(handshake_response, 1));
                //    MaxPackets = Math.Min(MaxPackets, BitConverter.ToInt32(handshake_response, 1 + sizeof(int)));
                //}
                //else
                //{
                //    // pokud nevyjde CRC nebo message neni typu Hanshake, je neco spatne...
                //    throw new Exception("Invalid hanshake message from target");
                //}

                MaxPacketLength = Math.Min(MaxPacketLength, BitConverter.ToUInt32(handshake_response, 1));
                MaxPackets      = Math.Min(MaxPackets, BitConverter.ToUInt32(handshake_response, 1 + sizeof(int)));

                _stop_and_wait = MaxPackets == 1;

                handshake_response = null;

                //dispose of older packets
                if (Packets != null)
                {
                    DisposePackets();
                }


                _packets = new DataPacket[MaxPackets];
                for (int i = 0; i < MaxPackets; ++i)
                {
                    _packets[i]          = new DataPacket();
                    _packets[i].Timeout += OnPacketTimeout;
                }

                _is_connected = true;
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error during connection to '{Target}': {e.Message}");
            }
        }