예제 #1
0
        public async void SendFileAsync(string addr, string filepath)
        {
            Message meta       = Message.CreateMeta(filepath, PackSize);
            string  status     = "";
            long    continueId = 0;

            try
            {
                status = "Wait Confirmation";
                IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(addr), ReceiverPort);
                UdpSend(remoteEP, meta);

                await WaitMessage(
                    msg => msg.Type == MsgType.Continue,
                    (remoteEP, msg) => continueId = msg.PackID);

                if (continueId == -1)
                {
                    OnTransferError?.Invoke(new State(ActionCode.FileSend, StateCode.Error, "Request rejected"));
                    return;
                }

                remoteEP.Port = TransferPort;
                status        = "Transferring";

                TcpSetupStream(remoteEP, ns =>
                {
                    using FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
                    byte[] bs           = null;
                    Message dataMsg     = new Message {
                        PackID = continueId, Data = new byte[PackSize]
                    };
                    fs.Seek((continueId - 1) * PackSize, SeekOrigin.Begin);
                    while (fs.Length - fs.Position > PackSize)
                    {
                        fs.Read(dataMsg.Data, 0, PackSize);
                        bs = dataMsg.ToBytes();
                        ns.Write(bs, 0, bs.Length);
                        ns.Flush();
                        dataMsg.PackID++;

                        OnPackTransfered?.Invoke((fs.Position / fs.Length));
                    }
                    fs.Read(dataMsg.Data, 0, (int)(fs.Length - fs.Position));
                    bs = dataMsg.ToBytes();
                    ns.Write(bs, 0, bs.Length);
                    ns.Flush();
                });
                OnTransferDone?.Invoke(new State(ActionCode.FileSend, StateCode.Success, ""));
            }
            catch (OperationCanceledException)
            {
                OnTransferError?.Invoke(new State(ActionCode.FileSend, StateCode.Error, status + " Timeout"));
            }
            catch (SocketException e)
            {
                OnTransferError?.Invoke(new State(ActionCode.FileSend, StateCode.Error, e.Message));
            }
        }
예제 #2
0
        private void ReceiveFile(IPEndPoint remoteEP, Message meta)
        {
            int continueId = LoadMetaFile(meta);

            UdpSend(remoteEP, new Message {
                PackID = continueId
            });

            TcpAcceptStream(ns =>
            {
                using (FileStream metafs = new FileStream(meta.Filename + ".meta", FileMode.Open))
                    using (FileStream fs = new FileStream(meta.Filename, FileMode.OpenOrCreate))
                        using (SHA256 sha = SHA256.Create())
                        {
                            Message data;
                            byte[] bs = new byte[meta.PackSize + 9];
                            for (int i = continueId - 1; i < meta.PackCount - 1; i++)
                            {
                                ns.Read(bs, 0, meta.PackSize + 9);
                                data = Message.Parse(bs);
                                fs.Seek(0, SeekOrigin.End);
                                fs.Write(data.Data, 0, meta.PackSize);
                                metafs.Seek(-8, SeekOrigin.End);
                                metafs.Write(Utils.GetBytes(data.PackID + 1), 0, 8);
                                fs.Flush(); metafs.Flush();

                                OnPackTransfered?.Invoke((i / meta.PackCount));
                            }
                            ns.Read(bs, 0, meta.PackSize + 9);
                            data = Message.Parse(bs);
                            fs.Write(data.Data, 0, (int)(meta.Size - meta.PackSize * (meta.PackCount - 1)));
                            fs.Flush();

                            fs.Seek(0, SeekOrigin.Begin);
                            metafs.Seek(0, SeekOrigin.Begin);
                            byte[] metahs = new byte[256];
                            metafs.Read(metahs, 0, 256);
                            byte[] hash = new byte[256];
                            byte[] t    = sha.ComputeHash(fs);
                            Array.Copy(t, 0, hash, 0, t.Length);
                            if (!hash.SequenceEqual(metahs))
                            {
                                throw new ChecksumMismatchException("Checksum not match, file may be collapsed.");
                            }
                        }
                File.Delete(meta.Filename + ".meta");
            });
        }