void Run(string[] args) { try { consoleWidth = Console.WindowWidth; } catch (IOException) { consoleWidth = 80; } Transport tsp = Transport.TCP; string endpoint = "*"; string subscription = String.Empty; DirectoryInfo tmpDir = null; List <DirectoryInfo> uploadDirs = new List <DirectoryInfo>(); DirectoryInfo baseDir = null; string basePath = null; bool recurseMode = true; List <FileInfo> files = new List <FileInfo>(); HashSet <string> ignoreFiles = new HashSet <string>(); HashSet <string> ignoreExtensions = new HashSet <string>(); bool listFiles = false; // Set default chunk size to 1MB: int chunkSize = 1024 * 1000; int ioThreads = 1; int hwm = 32; int pgmRate = 819200; Queue <string> argQueue = new Queue <string>(args); while (argQueue.Count > 0) { string arg = argQueue.Dequeue(); switch (arg) { case "-a": if (argQueue.Count == 0) { Console.Error.WriteLine("-a expects a transport name argument"); return; } tsp = (Transport)Enum.Parse(typeof(Transport), argQueue.Dequeue(), true); break; case "-e": if (argQueue.Count == 0) { Console.Error.WriteLine("-e expects an endpoint argument"); return; } endpoint = argQueue.Dequeue(); break; case "-r": if (argQueue.Count == 0) { Console.Error.WriteLine("-r expects a rate limit in kilobits per second argument"); return; } Int32.TryParse(argQueue.Dequeue(), out pgmRate); break; case "-d": if (argQueue.Count == 0) { Console.Error.WriteLine("-d expects a path argument"); return; } tmpDir = new DirectoryInfo(argQueue.Dequeue()); if (!tmpDir.Exists) { Console.Error.WriteLine("Directory '{0}' does not exist!", tmpDir.FullName); return; } uploadDirs.Add(tmpDir); // Set the base directory to this directory if the base was not already set: if ((baseDir == null) && (uploadDirs.Count == 1)) { baseDir = tmpDir; basePath = baseDir.FullName.EndsWith(Path.DirectorySeparatorChar.ToString()) ? baseDir.FullName : baseDir.FullName + Path.DirectorySeparatorChar; } // Add all files from the given directory, recursively or not, excluding any special '.lcc' download state folders/files: files.AddRange( from fi in (recurseMode ? tmpDir.GetFiles("*.*", SearchOption.AllDirectories) : tmpDir.GetFiles()) where fi.Directory.Name != ".lcc" where !ignoreFiles.Contains(fi.FullName.Substring(basePath.Length)) where !ignoreFiles.Contains(fi.Name) where !ignoreExtensions.Contains(fi.Extension) select fi ); // Now reorder the entire files list: files = ( from fi in files orderby fi.FullName select fi ).ToList(); break; case "-b": if (argQueue.Count == 0) { Console.Error.WriteLine("-b expects a path argument"); return; } string tmpS = argQueue.Dequeue(); baseDir = new DirectoryInfo(tmpS); if (!baseDir.Exists) { Console.Error.WriteLine("Directory '{0}' does not exist!", baseDir.FullName); return; } basePath = baseDir.FullName.EndsWith(Path.DirectorySeparatorChar.ToString()) ? baseDir.FullName : baseDir.FullName + Path.DirectorySeparatorChar; break; case "-i": if (argQueue.Count == 0) { Console.Error.WriteLine("-i expects a path argument"); return; } string ignorePath = argQueue.Dequeue(); if (!File.Exists(ignorePath)) { Console.Error.WriteLine("Could not open ignore file '{0}'", ignorePath); return; } // Set the ignoreFiles set to all the unique filenames found in the file: string[] lines = File.ReadAllLines(ignorePath); ignoreExtensions = new HashSet <string>( ( from line in lines where line.StartsWith("*.") select line.Substring(1) ).Distinct(StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase ); ignoreFiles = new HashSet <string>( lines.Except(ignoreExtensions).Distinct(StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase ); break; case "-m": recurseMode = true; break; case "-M": recurseMode = false; break; case "-s": if (argQueue.Count == 0) { Console.Error.WriteLine("-s expects a subscription name argument"); return; } subscription = argQueue.Dequeue(); break; case "-c": if (argQueue.Count == 0) { Console.Error.WriteLine("-c expects a chunk size argument"); return; } // Override the config with the commandline arg if it can be parsed: Int32.TryParse(argQueue.Dequeue(), out chunkSize); break; case "-n": if (argQueue.Count == 0) { Console.Error.WriteLine("-s expects a subscription name argument"); return; } Int32.TryParse(argQueue.Dequeue(), out ioThreads); break; case "-w": if (argQueue.Count == 0) { Console.Error.WriteLine("-w expects a high-water mark argument"); return; } Int32.TryParse(argQueue.Dequeue(), out hwm); break; case "-t": testMode = true; break; case "-?": DisplayUsage(); return; case "-l": listFiles = true; break; default: break; } } if ((uploadDirs.Count == 0) || String.IsNullOrEmpty(subscription)) { DisplayUsage(); return; } foreach (var fi in files) { if (!fi.FullName.StartsWith(basePath, StringComparison.OrdinalIgnoreCase)) { Console.Error.WriteLine("Directory '{0}' is not underneath the base directory '{1}'!", fi.Directory.FullName, baseDir.FullName); return; } } Console.WriteLine("Serving {0} files from '{1}':", files.Count, basePath); Console.WriteLine("{0,15} {1}", "Size (bytes)", "Path"); foreach (var fi in files) { string fiName = fi.FullName.Substring(basePath.Length); Console.WriteLine("{0,15} {1}", fi.Length.ToString("##,#"), fiName); } if (listFiles) { return; } using (var serverTarball = new TarballStreamWriter(files)) { var server = new LanCaster.ServerHost(tsp, endpoint, subscription, serverTarball, basePath, chunkSize, hwm, pgmRate, testMode); Console.WriteLine(); Console.WriteLine("{0,15} chunks @ {1,13} bytes/chunk", server.NumChunks.ToString("##,#"), server.ChunkSize.ToString("##,#")); server.ChunkSent += new Action <ServerHost, int>(ChunkSent); server.ChunksACKed += new Action <ServerHost>(ChunksACKed); server.ClientJoined += new Action <ServerHost, Guid>(ClientJoined); server.ClientLeft += new Action <ServerHost, Guid, ServerHost.ClientLeaveReason>(ClientLeft); // Begin the server thread: var serverThread = new Thread(server.Run); using (Context ctx = new Context(ioThreads)) { serverThread.Start(ctx); serverThread.Join(); } } }
void Run(string[] args) { try { consoleWidth = Console.WindowWidth; } catch (IOException) { consoleWidth = 80; } Transport tsp = Transport.TCP; string endpoint = "*"; string subscription = String.Empty; DirectoryInfo tmpDir = null; List<DirectoryInfo> uploadDirs = new List<DirectoryInfo>(); DirectoryInfo baseDir = null; string basePath = null; bool recurseMode = true; List<FileInfo> files = new List<FileInfo>(); HashSet<string> ignoreFiles = new HashSet<string>(); HashSet<string> ignoreExtensions = new HashSet<string>(); bool listFiles = false; // Set default chunk size to 1MB: int chunkSize = 1024 * 1000; int ioThreads = 1; int hwm = 32; int pgmRate = 819200; Queue<string> argQueue = new Queue<string>(args); while (argQueue.Count > 0) { string arg = argQueue.Dequeue(); switch (arg) { case "-a": if (argQueue.Count == 0) { Console.Error.WriteLine("-a expects a transport name argument"); return; } tsp = (Transport)Enum.Parse(typeof(Transport), argQueue.Dequeue(), true); break; case "-e": if (argQueue.Count == 0) { Console.Error.WriteLine("-e expects an endpoint argument"); return; } endpoint = argQueue.Dequeue(); break; case "-r": if (argQueue.Count == 0) { Console.Error.WriteLine("-r expects a rate limit in kilobits per second argument"); return; } Int32.TryParse(argQueue.Dequeue(), out pgmRate); break; case "-d": if (argQueue.Count == 0) { Console.Error.WriteLine("-d expects a path argument"); return; } tmpDir = new DirectoryInfo(argQueue.Dequeue()); if (!tmpDir.Exists) { Console.Error.WriteLine("Directory '{0}' does not exist!", tmpDir.FullName); return; } uploadDirs.Add(tmpDir); // Set the base directory to this directory if the base was not already set: if ((baseDir == null) && (uploadDirs.Count == 1)) { baseDir = tmpDir; basePath = baseDir.FullName.EndsWith(Path.DirectorySeparatorChar.ToString()) ? baseDir.FullName : baseDir.FullName + Path.DirectorySeparatorChar; } // Add all files from the given directory, recursively or not, excluding any special '.lcc' download state folders/files: files.AddRange( from fi in (recurseMode ? tmpDir.GetFiles("*.*", SearchOption.AllDirectories) : tmpDir.GetFiles()) where fi.Directory.Name != ".lcc" where !ignoreFiles.Contains(fi.FullName.Substring(basePath.Length)) where !ignoreFiles.Contains(fi.Name) where !ignoreExtensions.Contains(fi.Extension) select fi ); // Now reorder the entire files list: files = ( from fi in files orderby fi.FullName select fi ).ToList(); break; case "-b": if (argQueue.Count == 0) { Console.Error.WriteLine("-b expects a path argument"); return; } string tmpS = argQueue.Dequeue(); baseDir = new DirectoryInfo(tmpS); if (!baseDir.Exists) { Console.Error.WriteLine("Directory '{0}' does not exist!", baseDir.FullName); return; } basePath = baseDir.FullName.EndsWith(Path.DirectorySeparatorChar.ToString()) ? baseDir.FullName : baseDir.FullName + Path.DirectorySeparatorChar; break; case "-i": if (argQueue.Count == 0) { Console.Error.WriteLine("-i expects a path argument"); return; } string ignorePath = argQueue.Dequeue(); if (!File.Exists(ignorePath)) { Console.Error.WriteLine("Could not open ignore file '{0}'", ignorePath); return; } // Set the ignoreFiles set to all the unique filenames found in the file: string[] lines = File.ReadAllLines(ignorePath); ignoreExtensions = new HashSet<string>( ( from line in lines where line.StartsWith("*.") select line.Substring(1) ).Distinct(StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase ); ignoreFiles = new HashSet<string>( lines.Except(ignoreExtensions).Distinct(StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase ); break; case "-m": recurseMode = true; break; case "-M": recurseMode = false; break; case "-s": if (argQueue.Count == 0) { Console.Error.WriteLine("-s expects a subscription name argument"); return; } subscription = argQueue.Dequeue(); break; case "-c": if (argQueue.Count == 0) { Console.Error.WriteLine("-c expects a chunk size argument"); return; } // Override the config with the commandline arg if it can be parsed: Int32.TryParse(argQueue.Dequeue(), out chunkSize); break; case "-n": if (argQueue.Count == 0) { Console.Error.WriteLine("-s expects a subscription name argument"); return; } Int32.TryParse(argQueue.Dequeue(), out ioThreads); break; case "-w": if (argQueue.Count == 0) { Console.Error.WriteLine("-w expects a high-water mark argument"); return; } Int32.TryParse(argQueue.Dequeue(), out hwm); break; case "-t": testMode = true; break; case "-?": DisplayUsage(); return; case "-l": listFiles = true; break; default: break; } } if ((uploadDirs.Count == 0) || String.IsNullOrEmpty(subscription)) { DisplayUsage(); return; } foreach (var fi in files) { if (!fi.FullName.StartsWith(basePath, StringComparison.OrdinalIgnoreCase)) { Console.Error.WriteLine("Directory '{0}' is not underneath the base directory '{1}'!", fi.Directory.FullName, baseDir.FullName); return; } } Console.WriteLine("Serving {0} files from '{1}':", files.Count, basePath); Console.WriteLine("{0,15} {1}", "Size (bytes)", "Path"); foreach (var fi in files) { string fiName = fi.FullName.Substring(basePath.Length); Console.WriteLine("{0,15} {1}", fi.Length.ToString("##,#"), fiName); } if (listFiles) return; using (var serverTarball = new TarballStreamWriter(files)) { var server = new LanCaster.ServerHost(tsp, endpoint, subscription, serverTarball, basePath, chunkSize, hwm, pgmRate, testMode); Console.WriteLine(); Console.WriteLine("{0,15} chunks @ {1,13} bytes/chunk", server.NumChunks.ToString("##,#"), server.ChunkSize.ToString("##,#")); server.ChunkSent += new Action<ServerHost, int>(ChunkSent); server.ChunksACKed += new Action<ServerHost>(ChunksACKed); server.ClientJoined += new Action<ServerHost, Guid>(ClientJoined); server.ClientLeft += new Action<ServerHost, Guid, ServerHost.ClientLeaveReason>(ClientLeft); // Begin the server thread: var serverThread = new Thread(server.Run); using (Context ctx = new Context(ioThreads)) { serverThread.Start(ctx); serverThread.Join(); } } }