From 03f0ef112f773c5868374f194c612cc13ca385f8 Mon Sep 17 00:00:00 2001 From: icedream Date: Thu, 8 May 2014 13:31:33 +0200 Subject: [PATCH] Adding file transfer test app. Acts like an HTTP server. --- libnpsharp.sln | 6 + libnpsharp.sln.DotSettings | 1 + src/libnpsharp/NPClient.cs | 4 +- src/libnpsharp/NPFileException.cs | 9 +- src/npfile/App.config | 14 ++ src/npfile/Program.cs | 196 ++++++++++++++++++++++++++ src/npfile/Properties/AssemblyInfo.cs | 36 +++++ src/npfile/npfile.csproj | 78 ++++++++++ src/npfile/packages.config | 6 + src/npmotd/App.config | 10 +- src/npmotd/Program.cs | 1 + src/npmotd/npmotd.csproj | 1 - 12 files changed, 356 insertions(+), 6 deletions(-) create mode 100644 src/npfile/App.config create mode 100644 src/npfile/Program.cs create mode 100644 src/npfile/Properties/AssemblyInfo.cs create mode 100644 src/npfile/npfile.csproj create mode 100644 src/npfile/packages.config diff --git a/libnpsharp.sln b/libnpsharp.sln index 74eece0..628a6b0 100644 --- a/libnpsharp.sln +++ b/libnpsharp.sln @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{587B7B .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "npfile", "src\npfile\npfile.csproj", "{19EBF339-E076-4962-A671-5B44A978687D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,6 +30,10 @@ Global {7887D77B-3C79-44C5-AB80-944B191321BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {7887D77B-3C79-44C5-AB80-944B191321BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {7887D77B-3C79-44C5-AB80-944B191321BB}.Release|Any CPU.Build.0 = Release|Any CPU + {19EBF339-E076-4962-A671-5B44A978687D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19EBF339-E076-4962-A671-5B44A978687D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19EBF339-E076-4962-A671-5B44A978687D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19EBF339-E076-4962-A671-5B44A978687D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/libnpsharp.sln.DotSettings b/libnpsharp.sln.DotSettings index 300f99b..21542fa 100644 --- a/libnpsharp.sln.DotSettings +++ b/libnpsharp.sln.DotSettings @@ -1,4 +1,5 @@  + HTTP ID NP NPID diff --git a/src/libnpsharp/NPClient.cs b/src/libnpsharp/NPClient.cs index 57e8778..f2d99db 100644 --- a/src/libnpsharp/NPClient.cs +++ b/src/libnpsharp/NPClient.cs @@ -160,7 +160,7 @@ namespace NPSharp var result = (StorageUserFileMessage) packet; if (result.Result != 0) { - tcs.SetException(new NpFileException()); + tcs.SetException(new NpFileException(result.Result)); return; } tcs.SetResult(result.FileData); @@ -198,7 +198,7 @@ namespace NPSharp var result = (StoragePublisherFileMessage) packet; if (result.Result != 0) { - tcs.SetException(new NpFileException()); + tcs.SetException(new NpFileException(result.Result)); return; } tcs.SetResult(result.FileData); diff --git a/src/libnpsharp/NPFileException.cs b/src/libnpsharp/NPFileException.cs index 75c1153..6255477 100644 --- a/src/libnpsharp/NPFileException.cs +++ b/src/libnpsharp/NPFileException.cs @@ -7,8 +7,13 @@ namespace NPSharp { class NpFileException : Exception { - public NpFileException() - :base(@"Could not fetch file from NP server.") + internal NpFileException(int error) + : base(error == 1 ? @"File not found on NP server" : @"Internal error on NP server") + { + } + + internal NpFileException() + : base(@"Could not fetch file from NP server.") { } } diff --git a/src/npfile/App.config b/src/npfile/App.config new file mode 100644 index 0000000..a2dd99c --- /dev/null +++ b/src/npfile/App.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/npfile/Program.cs b/src/npfile/Program.cs new file mode 100644 index 0000000..6bbe903 --- /dev/null +++ b/src/npfile/Program.cs @@ -0,0 +1,196 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using log4net; +using log4net.Appender; +using log4net.Config; +using log4net.Core; +using log4net.Layout; +using NPSharp.Authentication; +using uhttpsharp; +using uhttpsharp.Handlers; +using uhttpsharp.Headers; +using uhttpsharp.Listeners; +using uhttpsharp.RequestProviders; + +namespace NPSharp.CommandLine.File +{ + class Program + { + static void Main(string[] args) + { + // log4net setup + var appender = new ColoredConsoleAppender + { +#if DEBUG + Threshold = Level.Debug, +#else + Threshold = Level.Info, +#endif + Layout = new PatternLayout("<%d{HH:mm:ss}> [%logger:%thread] %level: %message%newline"), + }; + appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = Level.Debug, ForeColor = ColoredConsoleAppender.Colors.Cyan | ColoredConsoleAppender.Colors.HighIntensity }); + appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = Level.Info, ForeColor = ColoredConsoleAppender.Colors.Green | ColoredConsoleAppender.Colors.HighIntensity }); + appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = Level.Warn, ForeColor = ColoredConsoleAppender.Colors.Purple | ColoredConsoleAppender.Colors.HighIntensity }); + appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = Level.Error, ForeColor = ColoredConsoleAppender.Colors.Red | ColoredConsoleAppender.Colors.HighIntensity }); + appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = Level.Fatal, ForeColor = ColoredConsoleAppender.Colors.White | ColoredConsoleAppender.Colors.HighIntensity, BackColor = ColoredConsoleAppender.Colors.Red }); + appender.ActivateOptions(); + BasicConfigurator.Configure(new IAppender[] { appender, new DebugAppender { Layout = appender.Layout, Threshold = Level.All } }); + + var log = LogManager.GetLogger("Main"); + + // Arguments + if (args.Length < 4) + { + log.ErrorFormat("Needs 4 arguments: nphostname npport username password [httpport]"); + return; + } + + var hostname = args[0]; + var port = ushort.Parse(args[1]); + var username = args[2]; + var password = args[3]; + var hport = args.Length > 4 ? ushort.Parse(args[4]) : 5680; + + // NP connection setup + log.DebugFormat("Connecting to {0}:{1}...", hostname, port); + var np = new NPClient(hostname, port); + if (!np.Connect()) + { + log.Error("Connection to NP server failed."); + return; + } + log.Info("NP connection successful, authenticating..."); + + // Get session token + var ah = new AuthenticationHelper(hostname); + try + { + ah.Authenticate(username, password); + np.AuthenticateWithToken(ah.SessionToken).Wait(); + log.Info("NP authentication successful."); + } + catch (Exception err) + { + np.Disconnect(); +#if DEBUG + log.ErrorFormat("Could not authenticate: {0}", err); +#else + log.ErrorFormat("Could not authenticate: {0}", err.Message); +#endif + return; + } + + // HTTP server + using (var httpServer = new HttpServer(new HttpRequestProvider())) + { + log.Info("Starting up HTTP server..."); + httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Any, hport))); + httpServer.Use(new HttpRouter() + .With("user", new NP2HTTPUserFileHandler(np)) + .With("pub", new NP2HTTPPublisherFileHandler(np)) + ); + httpServer.Use(new AnonymousHttpRequestHandler((context, next) => + { + context.Response = new HttpResponse(HttpResponseCode.NotFound, "File not found", context.Request.Headers.KeepAliveConnection()); + return Task.Factory.GetCompleted(); + })); + httpServer.Start(); + log.InfoFormat("HTTP server now running on port {0}.", hport); + log.InfoFormat("Access publisher files through http://{0}:{1}/pub/", IPAddress.Any, hport); + log.InfoFormat("Access user files through http://{0}:{1}/user/", IPAddress.Any, hport); + Thread.Sleep(Timeout.Infinite); + } + } + } + + internal class NP2HTTPUserFileHandler : IHttpRequestHandler + { + private readonly NPClient _np; + private readonly ILog _log; + + public NP2HTTPUserFileHandler(NPClient np) + { + _np = np; + _log = LogManager.GetLogger(GetType()); + } + + public Task Handle(IHttpContext context, Func next) + { + var uri = string.Join("/", context.Request.Uri.OriginalString.Split('/').Skip(2)); + + var task = _np.GetUserFile(uri); + try + { + task.Wait(); + } + catch + { + context.Response = HttpResponse.CreateWithMessage(HttpResponseCode.NotFound, "File not accessible", + context.Request.Headers.KeepAliveConnection(), + string.Format("
{0}
", task.Exception == null ? "Unknown error" : task.Exception.ToString()) + ); + using (var sw = new StreamWriter(new MemoryStream())) + { + sw.WriteLine("Content-type: {0}", "text/plain"); + sw.Flush(); + sw.BaseStream.Position = 0; + context.Response.WriteHeaders(sw); + } + return Task.Factory.GetCompleted(); + } + + // Return file contents + context.Response = new HttpResponse(HttpResponseCode.Ok, System.Web.MimeMapping.GetMimeMapping(uri), new MemoryStream(task.Result), context.Request.Headers.KeepAliveConnection()); + + return Task.Factory.GetCompleted(); + } + } + + internal class NP2HTTPPublisherFileHandler : IHttpRequestHandler + { + private readonly NPClient _np; + private readonly ILog _log; + + public NP2HTTPPublisherFileHandler(NPClient np) + { + _np = np; + _log = LogManager.GetLogger(GetType()); + } + + public Task Handle(IHttpContext context, Func next) + { + var uri = string.Join("/", context.Request.Uri.OriginalString.Split('/').Skip(2)); + + var task = _np.GetPublisherFile(uri); + try + { + task.Wait(); + } + catch + { + context.Response = HttpResponse.CreateWithMessage(HttpResponseCode.NotFound, "File not accessible", + context.Request.Headers.KeepAliveConnection(), + string.Format("
{0}
", task.Exception == null ? "Unknown error" : task.Exception.ToString()) + ); + using (var sw = new StreamWriter(new MemoryStream())) + { + sw.WriteLine("Content-type: {0}", "text/plain"); + sw.Flush(); + sw.BaseStream.Position = 0; + context.Response.WriteHeaders(sw); + } + return Task.Factory.GetCompleted(); + } + + // Return file contents + context.Response = new HttpResponse(HttpResponseCode.Ok, System.Web.MimeMapping.GetMimeMapping(uri), new MemoryStream(task.Result), context.Request.Headers.KeepAliveConnection()); + + return Task.Factory.GetCompleted(); + } + } +} diff --git a/src/npfile/Properties/AssemblyInfo.cs b/src/npfile/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e2932c5 --- /dev/null +++ b/src/npfile/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("npfile")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Hewlett-Packard")] +[assembly: AssemblyProduct("npfile")] +[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("549e5fde-a94d-4154-9577-5743f8be3ed3")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/npfile/npfile.csproj b/src/npfile/npfile.csproj new file mode 100644 index 0000000..ce483ad --- /dev/null +++ b/src/npfile/npfile.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {19EBF339-E076-4962-A671-5B44A978687D} + Exe + Properties + NPSharp.CommandLine.File + npfile + v4.5 + 512 + ..\..\ + true + + + true + full + false + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + TRACE + prompt + 4 + false + + + $(SolutionDir)\bin\$(Configuration)\$(Platform)\ + $(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\ + $(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\ + $(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\ + $(SolutionDir)\bin\$(Configuration)\$(Platform)\ + + + + ..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + + + ..\..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll + + + + + + ..\..\packages\uHttpSharp.0.1.4.7\lib\net40\uhttpsharp.dll + + + + + + + + + + + + + {1a5ac63a-250e-4bc8-b81a-822ac31f5e37} + libnpsharp + + + + + + \ No newline at end of file diff --git a/src/npfile/packages.config b/src/npfile/packages.config new file mode 100644 index 0000000..2a2f9af --- /dev/null +++ b/src/npfile/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/npmotd/App.config b/src/npmotd/App.config index 8e15646..a2dd99c 100644 --- a/src/npmotd/App.config +++ b/src/npmotd/App.config @@ -1,6 +1,14 @@ - + + + + + + + + + \ No newline at end of file diff --git a/src/npmotd/Program.cs b/src/npmotd/Program.cs index 65a725a..8da79ba 100644 --- a/src/npmotd/Program.cs +++ b/src/npmotd/Program.cs @@ -33,6 +33,7 @@ namespace NPSharp.CommandLine.MOTD var log = LogManager.GetLogger("Main"); + // Arguments if (args.Length < 4) { log.ErrorFormat("Needs 4 arguments: hostname port username password"); diff --git a/src/npmotd/npmotd.csproj b/src/npmotd/npmotd.csproj index d639486..178bdda 100644 --- a/src/npmotd/npmotd.csproj +++ b/src/npmotd/npmotd.csproj @@ -44,7 +44,6 @@ -