Beispiel #1
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...
        }
Beispiel #2
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;
            }
        }