Example #1
0
        /// <summary>
        /// Stops a download if one is running, checks if the donwnloader thread actually stops.
        /// </summary>
        /// <returns>true if stopped succesfully</returns>
        public bool AbortDownloader(int timeOut)
        {
            if (CheckIfDownloading())
            {
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("File " + CurrentFilePath + " will be deleted after aborting.", "DCC DOWNLOADER"));

                _shouldAbort = true;

                int timeout = 0;
                while (CheckIfDownloading())
                {
                    if (timeout > timeOut)
                    {
                        return(false);
                    }
                    timeout++;
                    Thread.Sleep(1);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #2
0
        /// <summary>
        /// Add a new Download to the queue
        /// </summary>
        /// <param name="ircData">The irc command.</param>
        /// <param name="downloadDirectory">The download directory.</param>
        /// <param name="bot">The bot.</param>
        /// <param name="packageNumber">The package number.</param>
        /// <param name="client">The client.</param>
        /// <returns>The created Download.</returns>
        public Download StartDownload(string ircData, string downloadDirectory, string bot, string packageNumber, IrcClient client)
        {
            var download = new Download(ircData, downloadDirectory, bot, packageNumber, client, _tokenSource.Token);

            download.OnDccDebugMessage += (sender, args) => OnDccDebugMessage?.Invoke(sender, args);
            download.OnDccEvent        += (sender, args) => OnDccEvent?.Invoke(sender, args);

            _downloadQueue.TryAdd(download, 0, _tokenSource.Token);

            return(download);
        }
Example #3
0
        /// <summary>
        /// Starts a downloader by parsing the received message from the irc server on information
        /// </summary>
        /// <param name="dccString">message from irc server</param>
        /// <param name="downloaddir">download directory</param>
        /// <param name="bot">bot where the file came from</param>
        /// <param name="pack">pack on bot where the file came from</param>
        /// <param name="client">irc client used the moment it received the dcc message, used for sending abort messages when download fails unexpectedly</param>
        public void StartDownloader(string dccString, string downloaddir, string bot, string pack, IrcClient client)
        {
            if ((dccString ?? downloaddir ?? bot ?? pack) != null && dccString.Contains("SEND") && !IsDownloading)
            {
                NewDccString    = dccString;
                _curDownloadDir = downloaddir;
                BotName         = bot;
                PackNum         = pack;
                _ircClient      = client;

                //parsing the data for downloader thread

                UpdateStatus("PARSING");
                bool isParsed = ParseData(dccString);

                //try to set the necesary information for the downloader
                if (isParsed)
                {
                    _shouldAbort = false;
                    //start the downloader thread
                    _downloader = new Thread(new ThreadStart(this.Downloader));
                    _downloader.IsBackground = true;
                    _downloader.Start();
                }
                else
                {
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs(
                                                  "Can't parse dcc string and start downloader, failed to parse data, removing from que\n", "DCC STARTER"));
                    _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum);
                    _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel");
                }
            }
            else
            {
                if (IsDownloading)
                {
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("You are already downloading! Ignore SEND request\n", "DCC STARTER"));
                }
                else
                {
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCC String does not contain SEND and/or invalid values for parsing! Ignore SEND request\n", "DCC STARTER"));
                }
            }
        }
Example #4
0
        /// <summary>
        /// Reverses IP from little endian to big endian or vice versa depending on what succeeds.
        /// </summary>
        /// <param name="ip">ip string</param>
        /// <returns>reversed ip string</returns>
        private string ReverseIp(string ip)
        {
            string[] parts = ip.Trim().Split('.');
            if (parts.Length >= 3)
            {
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("DCCClient: converting ip: " + ip, "DCC IP PARSER"));
                string NewIP = parts[3] + "." + parts[2] + "." + parts[1] + "." + parts[0];
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("DCCClient: to: " + NewIP, "DCC IP PARSER"));

                return(NewIP);
            }
            else
            {
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("DCCClient: converting ip: " + ip, "DCC IP PARSER"));
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("DCCClient: amount of parts: " + parts.Length, "DCC IP PARSER"));
                return("0.0.0.0");
            }
        }
Example #5
0
        /// <summary>
        /// Method ran within downloader thread, starts a connection to the file server, and receives the file accordingly, sends updates using event handler during the download.
        /// </summary>
        public void Downloader()
        {
            UpdateStatus("WAITING");

            Buffer = new List <byte>();

            //combining download directory path with filename

            if (_curDownloadDir != null)
            {
                if (_curDownloadDir != string.Empty)
                {
                    if (_curDownloadDir.Length > 0)
                    {
                        if (!Directory.Exists(_curDownloadDir))
                        {
                            Directory.CreateDirectory(_curDownloadDir);
                        }
                    }
                    else
                    {
                        _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads");
                        if (!Directory.Exists(_curDownloadDir))
                        {
                            Directory.CreateDirectory(_curDownloadDir);
                        }
                    }
                }
                else
                {
                    _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads");
                    if (!Directory.Exists(_curDownloadDir))
                    {
                        Directory.CreateDirectory(_curDownloadDir);
                    }
                }
            }
            else
            {
                _curDownloadDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Downloads");
                if (!Directory.Exists(_curDownloadDir))
                {
                    Directory.CreateDirectory(_curDownloadDir);
                }
            }

            string dlDirAndFileName = Path.Combine(_curDownloadDir, NewFileName);

            CurrentFilePath = dlDirAndFileName;
            try
            {
                if (!File.Exists(dlDirAndFileName))
                {
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("File does not exist yet, start connection with: " + NewIP + ":" + NewPortNum + Environment.NewLine, "DCC DOWNLOADER"));
                    Thread.Sleep(500);
                    //start connection with tcp server

                    IPAddress ip = IPAddress.Parse(NewIP);

                    using (TcpClient dltcp = new TcpClient(ip.AddressFamily))
                    {
                        dltcp.Connect(ip, NewPortNum);
                        using (NetworkStream dlstream = dltcp.GetStream())
                        {
                            //succesfully connected to tcp server, status is downloading
                            UpdateStatus("DOWNLOADING");

                            //values to keep track of progress
                            Int64    bytesReceived    = 0;
                            Int64    oldBytesReceived = 0;
                            Int64    oneprocent       = NewFileSize / 100;
                            DateTime start            = DateTime.Now;
                            bool     timedOut         = false;

                            //values to keep track of download position
                            int count;

                            //to me this buffer size seemed to be the most efficient.
                            byte[] buffer;
                            if (NewFileSize > 1048576)
                            {
                                OnDccDebugMessage?.Invoke(this,
                                                          new DCCDebugMessageArgs("Big file, big buffer (1 mb) \n ", "DCC DOWNLOADER"));
                                buffer = new byte[16384];
                            }
                            else if (NewFileSize < 1048576 && NewFileSize > 2048)
                            {
                                OnDccDebugMessage?.Invoke(this,
                                                          new DCCDebugMessageArgs("Smaller file (< 1 mb), smaller buffer (2 kb) \n ", "DCC DOWNLOADER"));
                                buffer = new byte[2048];
                            }
                            else if (NewFileSize < 2048 && NewFileSize > 128)
                            {
                                OnDccDebugMessage?.Invoke(this,
                                                          new DCCDebugMessageArgs("Small file (< 2kb mb), small buffer (128 b) \n ", "DCC DOWNLOADER"));
                                buffer = new byte[128];
                            }
                            else
                            {
                                OnDccDebugMessage?.Invoke(this,
                                                          new DCCDebugMessageArgs("Tiny file (< 128 b), tiny buffer (2 b) \n ", "DCC DOWNLOADER"));
                                buffer = new byte[2];
                            }


                            //create file to write to
                            using (FileStream writeStream = new FileStream(dlDirAndFileName, FileMode.Append, FileAccess.Write, FileShare.Read))
                            {
                                writeStream.SetLength(NewFileSize);
                                IsDownloading = true;
                                //download while connected and filesize is not reached
                                while (dltcp.Connected && bytesReceived < NewFileSize && !_shouldAbort)
                                {
                                    if (_shouldAbort)
                                    {
                                        dltcp.Close();
                                        dlstream.Dispose();
                                        writeStream.Close();
                                    }
                                    //keep track of progress
                                    DateTime end = DateTime.Now;
                                    if (end.Second != start.Second)
                                    {
                                        BytesPerSecond   = bytesReceived - oldBytesReceived;
                                        KBytesPerSecond  = (int)(BytesPerSecond / 1024);
                                        MBytesPerSecond  = (KBytesPerSecond / 1024);
                                        oldBytesReceived = bytesReceived;
                                        start            = DateTime.Now;
                                        UpdateStatus("DOWNLOADING");
                                        Buffer.Clear();
                                    }

                                    //count bytes received
                                    count = dlstream.Read(buffer, 0, buffer.Length);

                                    //write to buffer
                                    Buffer.AddRange(buffer);

                                    //write to file
                                    writeStream.Write(buffer, 0, count);

                                    //count bytes received
                                    bytesReceived += count;

                                    Progress = (int)(bytesReceived / oneprocent);
                                }

                                //close all connections and streams (just to be save)
                                dltcp.Close();
                                dlstream.Dispose();
                                writeStream.Close();

                                IsDownloading = false;

                                if (_shouldAbort)
                                {
                                    try
                                    {
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("Downloader Stopped", "DCC DOWNLOADER"));
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("File " + CurrentFilePath + " will be deleted due to aborting", "DCC DOWNLOADER"));
                                        File.Delete(CurrentFilePath);
                                    }
                                    catch (Exception e)
                                    {
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("File " + CurrentFilePath + " probably doesn't exist :X", "DCC DOWNLOADER"));
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs(e.ToString(), "DCC DOWNLOADER"));
                                    }

                                    UpdateStatus("ABORTED");
                                }
                                else
                                {
                                    //consider 95% downloaded as done, files are sequentually downloaded, sometimes download stops early, but the file still is usable
                                    if (Progress < 95 && !_shouldAbort)
                                    {
                                        UpdateStatus("FAILED");
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("Download stopped at < 95 % finished, deleting file: " + NewFileName + " \n", "DCC DOWNLOADER"));
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("Download stopped at : " + bytesReceived + " bytes, a total of " + Progress + "%", "DCC DOWNLOADER"));
                                        File.Delete(dlDirAndFileName);
                                        timedOut = false;
                                    }
                                    else if (timedOut && Progress < 95 && !_shouldAbort)
                                    {
                                        UpdateStatus("FAILED: TIMED OUT");
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("Download timed out at < 95 % finished, deleting file: " + NewFileName + " \n", "DCC DOWNLOADER"));
                                        OnDccDebugMessage?.Invoke(this,
                                                                  new DCCDebugMessageArgs("Download stopped at : " + bytesReceived + " bytes, a total of " + Progress + "%", "DCC DOWNLOADER"));
                                        File.Delete(dlDirAndFileName);
                                        timedOut = false;
                                    }
                                    else if (!_shouldAbort)
                                    {
                                        //make sure that in the event something happens and the downloader calls delete after finishing, the file will remain where it is.
                                        dlDirAndFileName = "";
                                        UpdateStatus("COMPLETED");
                                    }
                                }
                                _shouldAbort = false;
                            }
                        }
                    }
                }
                else
                {
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("File already exists, removing from xdcc que!\n", "DCC DOWNLOADER"));
                    _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum);
                    _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel");
                    UpdateStatus("FAILED: ALREADY EXISTS");
                }
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("File has been downloaded! \n File Location:" + CurrentFilePath, "DCC DOWNLOADER"));
            }
            catch (SocketException e)
            {
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("Something went wrong while downloading the file! Removing from xdcc que to be sure! Error:\n" + e.ToString(), "DCC DOWNLOADER"));
                _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum);
                _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel");
                UpdateStatus("FAILED: CONNECTING");
            }
            catch (Exception ex)
            {
                OnDccDebugMessage?.Invoke(this,
                                          new DCCDebugMessageArgs("Something went wrong while downloading the file! Removing from xdcc que to be sure! Error:\n" + ex.ToString(), "DCC DOWNLOADER"));
                _ircClient.SendMessageToAll("/msg " + BotName + " xdcc remove " + PackNum);
                _ircClient.SendMessageToAll("/msg " + BotName + " xdcc cancel");
                UpdateStatus("FAILED: UNKNOWN");
            }
            IsDownloading = false;
        }
Example #6
0
        /// <summary>
        /// Parses the received DCC string
        /// </summary>
        /// <param name="dccString">dcc string</param>
        /// <returns>returns true if parsing was succesfull, false if failed</returns>
        private bool ParseData(string dccString)
        {
            /*
             * :_bot PRIVMSG nickname :DCC SEND \"filename\" ip_networkbyteorder port filesize
             * [email protected] PRIVMSG WeebIRCDev :DCC SEND "[LNS] Death Parade - 02 [BD 720p] [7287AE5C].mkv" 633042523 59538 258271780
             * [email protected] PRIVMSG WeebIRCDev :DCC SEND [Coalgirls]_Spirited_Away_(1280x692_Blu-ray_FLAC)_[5805EE6B].mkv 3281692293 35567 10393049211
             * :[EWG][email protected] PRIVMSG LittleWeeb_jtokck :DCC SEND The.Good.Doctor.S01E13.Seven.Reasons.1080p.AMZN.WEB-DL.DD+5.1.H.264-QOQ.mkv 2655354388 55000 1821620363
             * Ginpa2:DCC SEND "[HorribleSubs] Dies Irae - 05 [480p].mkv" 84036312 35016 153772128
             */

            dccString = RemoveSpecialCharacters(dccString).Substring(1);
            OnDccDebugMessage?.Invoke(this,
                                      new DCCDebugMessageArgs("DCCClient: DCC STRING: " + dccString, "DCC PARSER"));


            if (!dccString.Contains(" :DCC"))
            {
                BotName = dccString.Split(':')[0];
                if (dccString.Contains("\""))
                {
                    NewFileName = dccString.Split('"')[1];

                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient1: FILENAME PARSED: " + NewFileName, "DCC PARSER"));
                    string[] thaimportantnumbers = dccString.Split('"')[2].Trim().Split(' ');
                    if (thaimportantnumbers[0].Contains(":"))
                    {
                        NewIP = thaimportantnumbers[0];
                    }
                    else
                    {
                        try
                        {
                            OnDccDebugMessage?.Invoke(this,
                                                      new DCCDebugMessageArgs("DCCClient1: PARSING FOLLOWING IPBYTES: " + thaimportantnumbers[0], "DCC PARSER"));
                            string ipAddress = UInt64ToIPAddress(Int64.Parse(thaimportantnumbers[0]));
                            NewIP = ipAddress;
                        }
                        catch
                        {
                            return(false);
                        }
                    }

                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient1: IP PARSED: " + NewIP, "DCC PARSER"));
                    NewPortNum  = int.Parse(thaimportantnumbers[1]);
                    NewFileSize = Int64.Parse(thaimportantnumbers[2]);

                    return(true);
                }
                else
                {
                    NewFileName = dccString.Split(' ')[2];


                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient2: FILENAME PARSED: " + NewFileName, "DCC PARSER"));

                    if (dccString.Split(' ')[3].Contains(":"))
                    {
                        NewIP = dccString.Split(' ')[3];
                    }
                    else
                    {
                        try
                        {
                            OnDccDebugMessage?.Invoke(this,
                                                      new DCCDebugMessageArgs("DCCClient2: PARSING FOLLOWING IPBYTES DIRECTLY: " + dccString.Split(' ')[3], "DCC PARSER"));
                            string ipAddress = UInt64ToIPAddress(Int64.Parse(dccString.Split(' ')[3]));
                            NewIP = ipAddress;
                        }
                        catch
                        {
                            return(false);
                        }
                    }
                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient2: IP PARSED: " + NewIP, "DCC PARSER"));
                    NewPortNum  = int.Parse(dccString.Split(' ')[4]);
                    NewFileSize = Int64.Parse(dccString.Split(' ')[5]);
                    return(true);
                }
            }
            else
            {
                BotName = dccString.Split('!')[0];
                if (dccString.Contains("\""))
                {
                    NewFileName = dccString.Split('"')[1];

                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient3: FILENAME PARSED: " + NewFileName, "DCC PARSER"));
                    string[] thaimportantnumbers = dccString.Split('"')[2].Trim().Split(' ');

                    if (thaimportantnumbers[0].Contains(":"))
                    {
                        NewIP = thaimportantnumbers[0];
                    }
                    else
                    {
                        try
                        {
                            OnDccDebugMessage?.Invoke(this,
                                                      new DCCDebugMessageArgs("DCCClient3: PARSING FOLLOWING IPBYTES DIRECTLY: " + thaimportantnumbers[0], "DCC PARSER"));
                            string ipAddress = UInt64ToIPAddress(Int64.Parse(thaimportantnumbers[0]));
                            NewIP = ipAddress;
                        }
                        catch
                        {
                            return(false);
                        }
                    }


                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient3: IP PARSED: " + NewIP, "DCC PARSER"));
                    NewPortNum  = int.Parse(thaimportantnumbers[1]);
                    NewFileSize = Int64.Parse(thaimportantnumbers[2]);
                    return(true);
                }
                else
                {
                    NewFileName = dccString.Split(' ')[5];

                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient4: FILENAME PARSED: " + NewFileName, "DCC PARSER"));

                    if (dccString.Split(' ')[6].Contains(":"))
                    {
                        NewIP = dccString.Split(' ')[6];
                    }
                    else
                    {
                        try
                        {
                            OnDccDebugMessage?.Invoke(this,
                                                      new DCCDebugMessageArgs("DCCClient4: PARSING FOLLOWING IPBYTES DIRECTLY: " + dccString.Split(' ')[6], "DCC PARSER"));
                            string ipAddress = UInt64ToIPAddress(Int64.Parse(dccString.Split(' ')[6]));
                            NewIP = ipAddress;
                        }
                        catch
                        {
                            return(false);
                        }
                    }

                    OnDccDebugMessage?.Invoke(this,
                                              new DCCDebugMessageArgs("DCCClient4: IP PARSED: " + NewIP, "DCC PARSER"));
                    NewPortNum  = int.Parse(dccString.Split(' ')[7]);
                    NewFileSize = Int64.Parse(dccString.Split(' ')[8]);
                    return(true);
                }
            }
        }