private void LocationResolvingThread() { int TimeoutValue = DefaultTimeoutValue * 4; // Allow for quarter-second sleep time ResolverTimeout = TimeoutValue; while (active && ResolverTimeout > 0) { if (ResolverQueue.Count > 0) { ClientInfoObject client = null; bool DequeueSuccessful = false; while (!(DequeueSuccessful)) { DequeueSuccessful = ResolverQueue.TryDequeue(out client); } client = GeolocationDatabase.ResolveLocation(client); IConsole.WriteLine(String.Format("[+] Address resolved: {0} -> {1}, {2}", client.address, client.City, client.Country)); ResolverTimeout = DefaultTimeoutValue; // Reset the timeout counter if (this.AddressResolvedEventSubscription != null) { this.AddressResolvedEventSubscription(client); } } else { ResolverTimeout--; Thread.Sleep(250); } } IConsole.PauseClearResume(); IConsole.WriteLine("[+] Initialized successfully."); }
// Binary search because I just don't have 1.5GB of free RAM public ClientInfoObject ResolveLocation(ClientInfoObject client) { int floor = 0; int ceiling = this.DatabaseLineCount - 1; if (ceiling > floor) { int DecimalAddress = IPStringToDecimal(client.address); while (true) { int middle = (int)Math.Floor((float)(floor + ceiling) / 2); String DatabaseLine = String.Empty; using (var FileHandle = File.OpenRead(DatabasePath)) { // Use the index cache to avoid repeatedly iterating the entire database FileHandle.Position = LineIndices[middle]; using (StreamReader LineReader = new StreamReader(FileHandle)) { DatabaseLine = LineReader.ReadLine(); } } DatabaseInfoObject AddressInfo = new DatabaseInfoObject(DatabaseLine); if (DecimalAddress > AddressInfo.AddressFloor && DecimalAddress < AddressInfo.AddressCeiling) { // Search succeeded client.SetAddressInfo(AddressInfo); break; } // Continue searching else if (DecimalAddress > AddressInfo.AddressCeiling) { floor = middle + 1; } else if (DecimalAddress < AddressInfo.AddressFloor) { ceiling = middle - 1; } else { // Search failed break; } } } return(client); }