Example #1
0
 void initUPnP()
 {
     for (int i = 0; i < 5; i++)
     {
         try
         {
             NatUtility.Initialize();
             NatUtility.DeviceFound += deviceFound;
             NatUtility.StartDiscovery();
             upnpSem.WaitOne();
             NatUtility.StopDiscovery();
             break;
         }
         catch (Exception e)
         {
             System.Threading.Thread.Sleep(1000);
             if (i < 5)
             {
                 SystemLog.addEntry("Failed to boot up UPnP. Exception: " + e.Message + ". Trying again...");
             }
             else
             {
                 SystemLog.addEntry("Giving up on UPnP and running a STUN instead...");
                 UPnPActive = false;
                 return;
             }
         }
     }
 }
Example #2
0
        async Task unMapPorts()
        {
            SystemLog.addEntry("Cleaning up UPnP mappings...");
            try
            {
                if (device == null)
                {
                    initUPnP();
                }
                externalIPFromUPnP = await device.GetExternalIPAsync();

                foreach (Mapping z in await device.GetAllMappingsAsync())
                {
                    if (z.Description == Environment.MachineName + " Dimension Mapping")
                    {
                        await device.DeletePortMapAsync(z);

                        SystemLog.addEntry("Successfully deleted UPnP mapping " + z.Description);
                        UPnPActive = true;
                    }
                }
            }
            catch
            {
                UPnPActive = false;
                SystemLog.addEntry("Failed to delete UPnP mapping.");
                //UPnP probably not supported
            }
        }
Example #3
0
        public FileListDatabase()
        {
            SystemLog.addEntry("Loading Databases...");

            string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

            folder = Path.Combine(folder, "Dimension");

            SystemLog.addEntry("Loading File List...");
            fileListPath = Path.Combine(folder, "FileList");
            fileList     = new RaptorDB.RaptorDB <string>(fileListPath, false);
            SystemLog.addEntry("Loading Quick Hashes...");
            quickHashes = new RaptorDB.RaptorDB <string>(Path.Combine(folder, "QuickHashes"), false);
            SystemLog.addEntry("Loading Full Hashes...");
            fullHashes = new RaptorDB.RaptorDB <string>(Path.Combine(folder, "FullHashes"), false);
            SystemLog.addEntry("Loading Download Queue...");
            downloadQueue = new RaptorDB.RaptorDB <string>(Path.Combine(folder, "DownloadQueue"), false);
            SystemLog.addEntry("Loading Remote File Lists...");
            remoteFileLists = new RaptorDB.RaptorDB <string>(Path.Combine(folder, "RemoteFileLists"), false);
            SystemLog.addEntry("Loading Search Lists...");
            searchListsPath = Path.Combine(folder, "SearchLists");
            searchList      = new RaptorDB.RaptorDB <string>(searchListsPath, false);

            SystemLog.addEntry("All Databases Loaded.");
        }
Example #4
0
        public Settings()
        {
            string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

            folder = Path.Combine(folder, "Dimension");

            SystemLog.addEntry("Loading Settings...");
            settings = new RaptorDB.RaptorDB <string>(Path.Combine(folder, "Settings"), false);
        }
Example #5
0
        public void endPunch(System.Net.IPEndPoint sender)
        {
            SystemLog.addEntry("Received BeginPunch from " + sender.ToString());
            System.Net.Sockets.Socket udp = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);

            udp.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0));
            SystemLog.addEntry("Bound " + udp.LocalEndPoint.ToString());

            byte[] b = App.serializer.serialize(new Commands.EndPunchCommand()
            {
                myId = App.theCore.id, port = (ushort)((System.Net.IPEndPoint)udp.LocalEndPoint).Port
            });
            if (isLocal)
            {
                foreach (System.Net.IPAddress a in internalAddress)
                {
                    SystemLog.addEntry("Sent EndPunch to " + new System.Net.IPEndPoint(a, localControlPort));
                    App.udpSend(b, new System.Net.IPEndPoint(a, localControlPort));
                }
            }
            else
            {
                SystemLog.addEntry("Sent EndPunch to " + actualEndpoint);
                App.udpSend(b, actualEndpoint);
            }
            System.Threading.Thread t = new System.Threading.Thread(delegate()
            {
                try
                {
                    Udt.Socket s   = new Udt.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream);
                    s.ReuseAddress = true;

                    s.Bind(udp);
                    s.Rendezvous = true;
                    SystemLog.addEntry("Beginning rendezvous...");
                    s.Connect(sender);
                    while (s.State == Udt.SocketState.Connecting)
                    {
                        System.Threading.Thread.Sleep(10);
                    }
                    App.theCore.addIncomingConnection(new UdtIncomingConnection(s, udp));

                    SystemLog.addEntry("Rendezvous successful!");
                }
                catch (Exception e)
                {
                    SystemLog.addEntry("Error rendezvous'ing to " + sender.ToString() + " - " + e.Message);
                }
            });
            t.Name         = "Rendezvous thread";
            t.IsBackground = true;
            t.Start();
        }
Example #6
0
        void partialUpdate(object sender, System.IO.FileSystemEventArgs e)
        {
            lock (updateLock)
            {
                quitComplete = false;
                RootShare[] shares = App.fileListDatabase.getRootShares();
                string      path   = e.FullPath.Replace('\\', '/');
                SystemLog.addEntry("Partial filesystem update to " + path.Replace('/', System.IO.Path.DirectorySeparatorChar));

                bool isFolder = System.IO.Directory.Exists(path);

                if (!isFolder)
                {
                    path     = path.Substring(0, path.LastIndexOf('/') + 1);
                    isFolder = System.IO.Directory.Exists(path);
                }
                if (isFolder)
                {
                    System.Threading.Thread t = new System.Threading.Thread(delegate()
                    {
                        foreach (RootShare r in shares)
                        {
                            if (r != null)
                            {
                                if (quitComplete)
                                {
                                    return;
                                }
                                if (path.StartsWith(r.fullPath + "/"))
                                {
                                    string remaining = path.Replace(System.IO.Path.DirectorySeparatorChar, '/').Substring(r.fullPath.Length + 1);
                                    FSListing f      = getFSListing("/" + (r.name + "/" + remaining).Trim('/'), true);

                                    if (f is Folder)
                                    {
                                        deleteFolder((Folder)f, false);
                                        loadFolder((Folder)f, false, path); //TODO: Update size of everything above this folder
                                    }
                                }
                            }
                        }
                        doSave();
                        if (updateComplete != null)
                        {
                            updateComplete();
                        }
                    });
                    t.IsBackground = true;
                    t.Name         = "Partial file list update thread";
                    t.Start();
                }
            }
        }
Example #7
0
        public void save()
        {
            lock (saveLock)
            {
                settings.SaveIndex();
                string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                folder = Path.Combine(folder, "Dimension");
                SystemLog.addEntry("Saving Settings...");

                /*settings.Dispose();
                 * settings = new RaptorDB.RaptorDB<string>(Path.Combine(folder, "Settings"), false);*/
            }
        }
Example #8
0
        System.Net.Sockets.TcpClient attemptConnection()
        {
            var t = new System.Net.Sockets.TcpClient();

            try
            {
                if (isLocal)
                {
                    t.Connect(new System.Net.IPEndPoint(_actualAddr, localDataPort));
                }
                else
                {
                    t.Connect(new System.Net.IPEndPoint(_actualAddr, externalDataPort));
                }
                return(t);
            }
            catch
            {
            }
            try
            {
                if (isLocal)
                {
                    for (int i = 0; i < internalAddress.Length; i++)
                    {
                        try
                        {
                            t.Connect(new System.Net.IPEndPoint(internalAddress[i], localDataPort));
                            return(t);
                        }
                        catch
                        {
                        }
                    }
                }
                else
                {
                    t.Connect(new System.Net.IPEndPoint(publicAddress, externalDataPort));
                    return(t);
                }
            }
            catch
            {
            }

            SystemLog.addEntry("Error reverse connecting to " + _actualAddr);

            return(null);
        }
Example #9
0
 //TODO: When updating shares, chew through File IDs less prodigiously
 //TODO: Update bottom-up instead of top-down -- so you don't need to do a complete list rebuild every time you change a file
 public void update(bool urgent)
 {
     lock (updateLock)
     {
         isUpdating = true;
         SystemLog.addEntry("Updating all shares" + (urgent ? " (urgently)" : ""));
         RootShare[] shares = App.fileListDatabase.getRootShares();
         foreach (RootShare r in shares)
         {
             if (r != null)
             {
                 updateRootShare(r, urgent);
                 if (System.IO.Directory.Exists(r.fullPath))
                 {
                     try
                     {
                         if (!watchers.ContainsKey(r.fullPath))
                         {
                             watchers[r.fullPath]          = new System.IO.FileSystemWatcher(r.fullPath);
                             watchers[r.fullPath].Changed += partialUpdate;
                             watchers[r.fullPath].Created += partialUpdate;
                             watchers[r.fullPath].Deleted += partialUpdate;
                             watchers[r.fullPath].Renamed += partialUpdate;
                             watchers[r.fullPath].IncludeSubdirectories = true;
                             watchers[r.fullPath].EnableRaisingEvents   = true;
                         }
                     }
                     catch (NotImplementedException)
                     {
                         //probably on mono, do nothing
                     }
                 }
             }
         }
     }
     quitComplete = true;
     quitSemaphore.Release();
     isUpdating = false;
     SystemLog.addEntry("Share update complete.");
     if (updateComplete != null)
     {
         updateComplete();
     }
 }
Example #10
0
        async Task mapPorts(int internalPort, int externalPort, bool tcp)
        {
            try
            {
                if (device == null)
                {
                    initUPnP();
                }
                externalIPFromUPnP = await device.GetExternalIPAsync();

                SystemLog.addEntry("Successfully found UPnP device " + await device.GetExternalIPAsync());

                Mapping m = new Mapping(tcp ? Protocol.Tcp : Protocol.Udp, internalPort, externalPort, Environment.MachineName + " Dimension Mapping");
                await device.CreatePortMapAsync(m);

                SystemLog.addEntry("Successfully created UPnP mapping from port " + internalPort.ToString() + " to " + externalPort.ToString());
                UPnPActive = true;
            }
            catch
            {
                UPnPActive = false;
                //UPnP probably not supported
            }
        }
Example #11
0
        public void createConnection(MessageResponseDelegate response = null)
        {
            bool createData = true;

            if (dataConnection != null)
            {
                if (dataConnection.connected)
                {
                    createData = false;
                }
            }
            bool createControl = true;

            if (controlConnection != null)
            {
                if (controlConnection.connected)
                {
                    createControl = false;
                }
            }
            if (createControl == false && createData == false)
            {
                return;
            }
            if (id == App.theCore.id)
            {
                response?.Invoke("Loopback peer found, creating loopback connection...");
                if (createControl)
                {
                    controlConnection = new LoopbackOutgoingConnection();
                }
                if (createData)
                {
                    dataConnection = new LoopbackOutgoingConnection();
                }
            }
            else
            {
                if (isLocal && internalAddress != null)
                {
                    response?.Invoke("Local peer found.");
                    if (internalAddress.Length > 1)
                    {
                        response?.Invoke("Multiple local addresses found. Trying each...");
                    }

                    for (int i = 0; i < internalAddress.Length; i++)
                    {
                        actualEndpoint = new System.Net.IPEndPoint(internalAddress[i], localControlPort);

                        bool reverseConnect = false;
                        if (App.settings.getBool("Default to Reverse Connection", false))
                        {
                            reverseConnect = true;
                        }
                        bool rendezvousConnect = false;
                        if (App.settings.getBool("Always Rendezvous", false) && useUDT)
                        {
                            reverseConnect    = false;
                            rendezvousConnect = true;
                        }
                        if (!reverseConnect && !rendezvousConnect)
                        {
                            try
                            {
                                if (createControl && controlConnection == null)
                                {
                                    response?.Invoke("Creating TCP connection to " + actualEndpoint.Address.ToString() + ":" + localDataPort.ToString());
                                    controlConnection = new ReliableOutgoingConnection(actualEndpoint.Address, localDataPort);
                                }
                                if (createData && dataConnection == null)
                                {
                                    response?.Invoke("Creating TCP connection to " + actualEndpoint.Address.ToString() + ":" + localDataPort.ToString());
                                    dataConnection = new ReliableOutgoingConnection(actualEndpoint.Address, localDataPort);
                                }
                            }
                            catch (Exception e)
                            {
                                SystemLog.addEntry("Failed to connect to " + actualEndpoint.Address.ToString());
                                reverseConnect = true;
                            }
                        }
                        if (reverseConnect)
                        {
                            doReverseConnection(response);
                            return;
                        }
                        if (rendezvousConnect)
                        {
                            doRendezvous(response);
                            return;
                        }
                    }
                }
                else
                {
                    bool reverseConnect = false;
                    if (App.settings.getBool("Default to Reverse Connection", false))
                    {
                        reverseConnect = true;
                    }
                    bool rendezvousConnect = false;
                    if (App.settings.getBool("Always Rendezvous", false) && useUDT)
                    {
                        reverseConnect    = false;
                        rendezvousConnect = true;
                    }

                    if (!reverseConnect && !rendezvousConnect)
                    {
                        try
                        {
                            if (createControl)
                            {
                                response?.Invoke("Creating TCP connection to " + actualEndpoint.Address.ToString() + ":" + externalDataPort.ToString());
                                controlConnection = new ReliableOutgoingConnection(actualEndpoint.Address, externalDataPort);
                            }
                            if (createData)
                            {
                                response?.Invoke("Creating TCP connection to " + actualEndpoint.Address.ToString() + ":" + externalDataPort.ToString());
                                dataConnection = new ReliableOutgoingConnection(actualEndpoint.Address, externalDataPort);
                            }
                        }
                        catch (System.Net.Sockets.SocketException s)
                        {
                            response?.Invoke("Error: " + s.Message + ".");
                            reverseConnect = true;
                        }
                    }
                    if (reverseConnect)
                    {
                        doReverseConnection(response);
                        return;
                    }
                    if (rendezvousConnect)
                    {
                        doRendezvous(response);
                        return;
                    }
                }
            }
            if (createData)
            {
                if (dataConnection != null && dataConnection != controlConnection)
                {
                    dataConnection.commandReceived += commandReceived;
                }
            }
            if (createControl && controlConnection != null)
            {
                controlConnection.commandReceived += commandReceived;
            }
            System.Threading.Thread.Sleep(500);
        }
Example #12
0
 public override void Write(string message)
 {
     SystemLog.addEntry(message);
 }
Example #13
0
        public async Task launch()
        {
            SystemLog.addEntry("Beginning network setup...");
            SystemLog.addEntry("Deleting old UPnP mappings...");
            if (App.settings.getBool("Use UPnP", true))
            {
                bool done = false;
                System.Threading.Semaphore s = new System.Threading.Semaphore(0, 1);
                System.Threading.Thread t = new System.Threading.Thread(async delegate()
                {
                    await unMapPorts();
                    done = true;
                    s.Release();
                });
                t.IsBackground = true;
                t.Name         = "UPnP test thread";
                t.Start();

                if (!done)
                {
                    s.WaitOne(10000);
                }
                if (!done)
                {
                    SystemLog.addEntry("Failed to find UPnP router in a timely fashion. Disabling UPnP...");
                    UPnPActive = false;
                }
            }
            SystemLog.addEntry("Binding UDP sockets.");
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);


            listener = new TcpListener(IPAddress.Any, App.settings.getInt("Default Data Port", 0));

            listener.Start();
            internalDataPort = ((IPEndPoint)listener.Server.LocalEndPoint).Port;
            SystemLog.addEntry("Binding to TCP port " + internalDataPort.ToString());
            int control = App.settings.getInt("Default Control Port", 0);

            if (control == Dimension.Model.NetConstants.controlPort)
            {
                control = 0;
            }
            unreliableClient    = new UdpClient(control);
            internalControlPort = ((IPEndPoint)unreliableClient.Client.LocalEndPoint).Port;
            if (control == 0)
            {
                App.settings.setInt("Default Control Port", internalControlPort);
            }
            SystemLog.addEntry("Successfully bound to UDP control port " + internalControlPort);

            publicControlEndPoint = (IPEndPoint)unreliableClient.Client.LocalEndPoint;
            publicDataEndPoint    = (IPEndPoint)listener.Server.LocalEndPoint;

tryAgain:

            if (App.settings.getBool("Use UPnP", true) == false || LANMode || !UPnPActive || behindDoubleNAT)
            {
                SystemLog.addEntry("STUNning NAT");
                try
                {
                    string      stunUrl = "stun.l.google.com";
                    STUN_Result result  = STUN_Client.Query(stunUrl, 19302, unreliableClient.Client);
                    SystemLog.addEntry("Attempting to STUN control port to " + stunUrl + ".");

                    if (result.NetType == STUN_NetType.UdpBlocked)
                    {
                        SystemLog.addEntry("STUN failed. Assuming network is LAN-only.");
                        LANMode    = true;
                        UPnPActive = false;
                    }
                    else
                    {
                        publicControlEndPoint = new IPEndPoint(result.PublicEndPoint.Address, result.PublicEndPoint.Port);
                        publicDataEndPoint    = new IPEndPoint(result.PublicEndPoint.Address, internalDataPort);
                        SystemLog.addEntry("STUN successful. External control endpoint: " + result.PublicEndPoint.ToString());
                        SystemLog.addEntry("External data endpoint: " + publicDataEndPoint.ToString());
                    }
                }
                catch (Exception) //STUN can throw generic exceptions :(
                {
                    SystemLog.addEntry("Failed to STUN. Working in LAN mode.");
                    //Stun failed, offline mode
                    LANMode = true;
                }
            }



            Random r = new Random();

            internalDHTPort = App.settings.getInt("Default DHT Port", 0);
            if (internalDHTPort == 0)
            {
                internalDHTPort = r.Next(short.MaxValue - 1000) + 1000;
            }
            publicDHTPort = internalDHTPort;
            if (App.settings.getBool("Use UPnP", true) && !LANMode && UPnPActive && !behindDoubleNAT)
            {
                SystemLog.addEntry("UPnP enabled. Attempting to map UPnP ports...");

                publicControlEndPoint = new IPEndPoint(publicControlEndPoint.Address, r.Next(short.MaxValue - 1000) + 1000);
                publicDataEndPoint    = new IPEndPoint(publicControlEndPoint.Address, r.Next(short.MaxValue - 1000) + 1000);
                publicDHTPort         = r.Next(short.MaxValue - 1000) + 1000;

                SystemLog.addEntry("Creating control UPnP mapping (random external port)...");
                await mapPorts(((IPEndPoint)unreliableClient.Client.LocalEndPoint).Port, publicControlEndPoint.Port, false);

                SystemLog.addEntry("Creating data UPnP mapping (random external port)...");
                await mapPorts(((IPEndPoint)listener.Server.LocalEndPoint).Port, publicDataEndPoint.Port, true);

                SystemLog.addEntry("Creating DHT UPnP mapping (random external port)...");
                await mapPorts(internalDHTPort, publicDHTPort, false);

                publicControlEndPoint = new IPEndPoint(externalIPFromUPnP, publicControlEndPoint.Port);
                publicDataEndPoint    = new IPEndPoint(externalIPFromUPnP, publicDataEndPoint.Port);

                if (externalIPFromUPnP.ToString().StartsWith("10.") || externalIPFromUPnP.ToString().StartsWith("192."))
                {
                    behindDoubleNAT = true;
                    SystemLog.addEntry("WARNING! Your router provided a local IP address as the external endpoint.");
                    SystemLog.addEntry("This probably means you're running more than one router in a row (double NAT).");
                    SystemLog.addEntry("Dimension is going to disable UPnP and try STUNning again to get through this.");
                    SystemLog.addEntry("If this is your home network, please talk to a network engineer -- having UPnP with double NAT is a very bad idea.");
                    goto tryAgain;
                }
            }
            SystemLog.addEntry("Network setup complete.");
        }
Example #14
0
        void updateRootShare(RootShare f, bool urgent)
        {
            lock (toSave)
                toSave.Clear();
            if (quitting)
            {
                return;
            }
            f.id = App.fileListDatabase.allocateId();
            ulong size = 0;

            SystemLog.addEntry("Updating root share " + f.fullPath.Replace('/', System.IO.Path.DirectorySeparatorChar) + "...");
            sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            string path = "";

            path = f.fullPath;

            bool invalidated = false;

            System.IO.DirectoryInfo d = new System.IO.DirectoryInfo(path);
            if (d.LastWriteTimeUtc.Ticks != f.lastModified)
            {
                invalidated = true;
            }
            string s = "";

            try
            {
                if (d.GetFiles().Length + d.GetDirectories().Length != f.folderIds.Length + f.fileIds.Length)
                {
                    invalidated = true;
                }
                foreach (System.IO.FileInfo i in d.GetFiles())
                {
                    s += i.Name + "|" + i.Length.ToString() + "|" + i.LastWriteTimeUtc.Ticks.ToString() + Environment.NewLine;
                    wait(urgent);
                }
                foreach (System.IO.DirectoryInfo i in d.GetDirectories())
                {
                    s += i.Name + "|" + i.LastWriteTimeUtc.Ticks.ToString() + Environment.NewLine;
                    wait(urgent);
                }
            }
            catch (System.IO.IOException)
            {
                return;
            }
            string s2 = "";

            foreach (ulong id in f.fileIds)
            {
                File i = App.fileListDatabase.getObject <File>(App.fileListDatabase.fileList, "FSListing " + id.ToString());

                if (i != null)
                {
                    size += i.size;
                    s2   += i.name + "|" + i.size + "|" + i.lastModified.ToString() + Environment.NewLine;
                }
                wait(urgent);
            }
            foreach (ulong id in f.folderIds)
            {
                Folder i = App.fileListDatabase.getObject <Folder>(App.fileListDatabase.fileList, "FSListing " + id.ToString());

                if (i != null)
                {
                    size += i.size;
                    s2   += i.name + "|" + i.lastModified.ToString() + Environment.NewLine;
                }
                wait(urgent);
            }
            if (s != s2)
            {
                invalidated = true;
            }

            if (invalidated)
            {
                deleteFolder(f, urgent);
                size   = loadFolder(f, urgent, path);
                f.size = size;
                lock (toSave)
                    toSave["FSListing " + f.id] = f;
                if (!quitting)
                {
                    App.fileListDatabase.setObject(App.settings.settings, "Root Share " + f.index.ToString(), f);
                    doSave();
                }
            }
            sw.Stop();
            sw.Reset();
        }