예제 #1
0
        /// <summary>
        /// Manage the connected client
        /// </summary>
        /// <param name="result">TCPClient object</param>
        /// <returns>Return a task, it is used to allow the Task asynchronous programming model (TAP)</returns>
        public async Task ServeClient(object result)
        {
            NetworkStream stream = null;
            TcpClient     client = null;
            Dictionary <string, FileRecvStatus> updateRecvDictionary = new Dictionary <string, FileRecvStatus>();
            Dictionary <string, FileSendStatus> updateSendDictionary = new Dictionary <string, FileSendStatus>();

            try {
                client = (TcpClient)result;
                Console.WriteLine($"{DateTime.Now.ToString()}\t - TCPListener Client connected! {((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString()}");

                byte[] bytes = new byte[1 + 256 + 8];
                stream = client.GetStream();

                int i = 0;
                if ((i = await stream.ReadAsync(bytes, 0, bytes.Length)) != 0)
                {
                    // The first byte define the type of the packet
                    byte[] readPacket = new byte[1];
                    Array.Copy(bytes, 0, readPacket, 0, 1);

                    // If it is not correct, send an Exception
                    if ((int)readPacket[0] > 5)
                    {
                        throw new Exception($"Packet not valid");
                    }

                    // The following 256 bytes are the name of the file (UTF8 coding)
                    PacketType type = (PacketType)readPacket[0];
                    readPacket = new byte[256];
                    Array.Copy(bytes, 1, readPacket, 0, 256);
                    string       filename = "";
                    UTF8Encoding encoder;

                    // Trown an exception in case the sequence of bytes cannot be converted as a stirng
                    try {
                        encoder  = new UTF8Encoding();
                        filename = encoder.GetString(readPacket);
                        filename = filename.Replace("\0", string.Empty);
                    }
                    catch (Exception e) {
                        throw new Exception($"Packet not valid - Reason {e.Message}");
                    }
                    long dimFile = 0;

                    string ipClient = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();

                    switch (type)
                    {
                    case PacketType.RFILE:
                        if (_referenceData.GetInfoLocalUser().AcceptAllFile)
                        {
                            _referenceData.AddOrUpdateRecvStatus(ipClient, filename, FileRecvStatus.YSEND);

                            await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                                MainWindow.main.AddOrUpdateListFile(ipClient, filename, FileRecvStatus.YSEND, "-", 0.0f);
                                MainWindow.main.NotifySistem();
                                MainWindow.main.SendResponse(filename, ipClient, PacketType.YFILE);
                            }));
                        }
                        else
                        {
                            _referenceData.AddOrUpdateRecvStatus(ipClient, filename, FileRecvStatus.TOCONF);

                            await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                                MainWindow.main.AddOrUpdateListFile(ipClient, filename, FileRecvStatus.TOCONF, "-", 0.0f);
                                MainWindow.main.NotifySistem();
                            }));
                        }
                        break;

                    case PacketType.YFILE:
                        if (_referenceData.UpdateSendStatusFileForUser(ipClient, filename, FileSendStatus.CONFERMED))
                        {
                            await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                                MainWindow.main.AddOrUpdateListFile(ipClient, filename, FileSendStatus.CONFERMED, "-", 0);
                                MainWindow.main.SendFile(filename, ipClient);
                            }));
                        }
                        else
                        {
                            throw new Exception("No file with name " + filename + " was announced from this client");
                        }
                        break;

                    case PacketType.NFILE:
                        if (_referenceData.UpdateSendStatusFileForUser(ipClient, filename, FileSendStatus.REJECTED))
                        {
                            await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                                MainWindow.main.AddOrUpdateListFile(ipClient, filename, FileSendStatus.REJECTED, "-", 0);
                                MainWindow.main.SendFile(filename, ipClient);
                            }));
                        }
                        else
                        {
                            throw new Exception("No file with name " + filename + " was announced from this client");
                        }
                        break;

                    case PacketType.FSEND:
                    {
                        if (_referenceData.CheckPacketRecvFileStatus(ipClient, filename))
                        {
                            throw new Exception("File with name " + filename + " never confirmed or need to be resend to the user");
                        }
                        string fileNameOriginal = filename;

                        readPacket = new byte[8];
                        Array.Copy(bytes, 257, readPacket, 0, 8);
                        try {
                            dimFile = BitConverter.ToInt64(readPacket, 0);
                        }
                        catch (Exception e) {
                            throw new Exception($"Packet not valid - Reason {e.Message}");
                        }
                        await ServeReceiveFile(client, stream, ipClient, filename, dimFile);
                    }
                    break;

                    case PacketType.CIMAGE:
                        readPacket = new byte[8];
                        Array.Copy(bytes, 257, readPacket, 0, 8);
                        try {
                            dimFile = BitConverter.ToInt64(readPacket, 0);
                        }
                        catch (Exception e) {
                            throw new Exception($"Packet not valid - Reason {e.Message}");
                        }
                        await ServeReceiveProfileImage(client, stream, ipClient, filename, dimFile);

                        break;
                    }
                }
            }
            catch (SocketException e) {
                Console.WriteLine($"{DateTime.Now.ToString()}\t - Serve TCPClient SocketException - {e.Message}");
            }
            catch (Exception e) {
                Console.WriteLine($"{DateTime.Now.ToString()}\t - Serve TCPClient Exception - {e.GetType()} {e.Message}");
            }
            finally {
                stream.Close();
                client.Close();
            }
        }
예제 #2
0
        /// <summary>
        /// Send file to the remote user that accept it
        /// </summary>
        /// <param name="filename">File name</param>
        /// <param name="ip">Ip remote user</param>
        public async Task SendFile(string filename, string ip)
        {
            // Check if the file is in a status to be rended or if it was confirmed
            if (!_referenceData.CheckPacketSendFileStatus(ip, filename))
            {
                return;
            }
            if (_referenceData.GetUserStatus(ip).Equals("offline"))
            {
                _referenceData.UpdateSendStatusFileForUser(ip, Utility.PathToFileName(filename), FileSendStatus.RESENT);

                await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.RESENT, "-", 0);
                }));

                return;
            }
            IPAddress serverAddr = IPAddress.Parse(ip);

            // In case of exception resend the packet three times
            TcpClient     client = null;
            NetworkStream stream = null;

            if (!_referenceData.CheckPacketSendFileStatus(ip, filename))
            {
                return;
            }

            try {
                client = new TcpClient();
                await client.ConnectAsync(serverAddr.ToString(), SharedInfo.TCPPort).ConfigureAwait(false);

                byte[] bytes = new byte[1 + 256 + 8];

                // 1^ byte: packet type
                bytes[0] = (byte)PacketType.FSEND;

                // Following 256 bytes : file name
                UTF8Encoding encorder = new UTF8Encoding();
                encorder.GetBytes(Utility.PathToFileName(filename)).CopyTo(bytes, 1);

                // Open file image
                filename = Utility.PathTmp() + "\\" + filename;
                using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize * 1024, FileOptions.Asynchronous | FileOptions.SequentialScan))
                {
                    // Following 8 bytes : file legth
                    BitConverter.GetBytes(file.Length).CopyTo(bytes, 257);

                    stream = client.GetStream();

                    // Primi 265 byte di header
                    await stream.WriteAsync(bytes, 0, 265).ConfigureAwait(false);

                    _referenceData.UpdateSendStatusFileForUser(serverAddr.ToString(), Utility.PathToFileName(filename), FileSendStatus.INPROGRESS);

                    await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                        MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.INPROGRESS, "-", 0);
                    }));

                    // First 297 : header
                    bytes = new byte[bufferSize * 64];

                    int      i;
                    long     dataReceived             = file.Length;
                    uint     estimatedTimePacketCount = 0;
                    double   numerator     = 0.0;
                    double   estimateTime  = 0.0;
                    DateTime started       = DateTime.Now;
                    TimeSpan estimatedTime = TimeSpan.FromSeconds(0);

                    while (((i = file.Read(bytes, 0, bytes.Length)) != 0) && dataReceived >= 0)
                    {
                        double dataReceivedJet = 0.0f;

                        if (_referenceData.CheckSendStatusFile(ip, Utility.PathToFileName(filename), FileSendStatus.REJECTED))
                        {
                            throw new RejectedFileException("File is rejected by remote host");
                        }

                        if (_referenceData.GetUserStatus(ip).Equals("offline"))
                        {
                            throw new Exception("User offline");
                        }

                        if (dataReceived > 0 && dataReceived < i)
                        {
                            await stream.WriteAsync(bytes, 0, Convert.ToInt32(dataReceived));

                            dataReceivedJet = 100f;
                        }
                        else
                        {
                            await stream.WriteAsync(bytes, 0, i);

                            dataReceivedJet = Math.Ceiling((double)(file.Length - dataReceived) / ((double)file.Length) * 100);
                        }
                        dataReceived -= i;


                        if (estimatedTimePacketCount < 5)
                        {
                            numerator += (double)(file.Length - dataReceived);
                            estimatedTimePacketCount++;
                        }
                        else
                        {
                            TimeSpan elapsedTime = DateTime.Now - started;

                            estimateTime  = elapsedTime.TotalSeconds * dataReceived / numerator;
                            estimatedTime = TimeSpan.FromSeconds(estimateTime);

                            numerator = 0.0;
                            estimatedTimePacketCount = 0;
                        }
                        string estimatedTimeJet = string.Format("{00:00}", estimatedTime.Minutes) + ":" +
                                                  string.Format("{00:00}", estimatedTime.Seconds) + ":" +
                                                  string.Format("{00:00}", estimatedTime.Milliseconds);
                        await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                            MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.INPROGRESS, estimatedTimeJet, dataReceivedJet);
                        }));
                    }
                }
                _referenceData.UpdateSendStatusFileForUser(serverAddr.ToString(), Utility.PathToFileName(filename), FileSendStatus.END);

                await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.END, "-", 100);
                }));
            } catch (RejectedFileException e) {
                Console.WriteLine($"{DateTime.Now.ToString()}\t - RejectedFileException on SendFile - {e.Message}");

                await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.REJECTED, "-", 0);
                }));
            } catch (SocketException e) {
                Console.WriteLine($"{DateTime.Now.ToString()}\t - SocketException on SendFile - {e.Message}");

                _referenceData.UpdateSendStatusFileForUser(serverAddr.ToString(), Utility.PathToFileName(filename), FileSendStatus.REJECTED);

                await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.REJECTED, "-", 0);
                }));
            }
            catch (Exception e) {
                Console.WriteLine($"{DateTime.Now.ToString()}\t - Exception on SendFile - {e.Message}");
                // If the remote host was offline, try to resend it for three times
                _referenceData.UpdateSendStatusFileForUser(serverAddr.ToString(), Utility.PathToFileName(filename), FileSendStatus.REJECTED);

                await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    MainWindow.main.AddOrUpdateListFile(ip, Utility.PathToFileName(filename), FileSendStatus.REJECTED, "-", 0);
                }));
            }
            finally {
                client.Close();
                stream.Close();
            }
        }