Adding file transfer test app. Acts like an HTTP server.

feature-npv2
Icedream 2014-05-08 13:31:33 +02:00
parent 6555e2f24d
commit 03f0ef112f
12 changed files with 356 additions and 6 deletions

View File

@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{587B7B
.nuget\NuGet.targets = .nuget\NuGet.targets .nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "npfile", "src\npfile\npfile.csproj", "{19EBF339-E076-4962-A671-5B44A978687D}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{7887D77B-3C79-44C5-AB80-944B191321BB}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HTTP/@EntryIndexedValue">HTTP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NP/@EntryIndexedValue">NP</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NP/@EntryIndexedValue">NP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NPID/@EntryIndexedValue">NPID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NPID/@EntryIndexedValue">NPID</s:String>

View File

@ -160,7 +160,7 @@ namespace NPSharp
var result = (StorageUserFileMessage) packet; var result = (StorageUserFileMessage) packet;
if (result.Result != 0) if (result.Result != 0)
{ {
tcs.SetException(new NpFileException()); tcs.SetException(new NpFileException(result.Result));
return; return;
} }
tcs.SetResult(result.FileData); tcs.SetResult(result.FileData);
@ -198,7 +198,7 @@ namespace NPSharp
var result = (StoragePublisherFileMessage) packet; var result = (StoragePublisherFileMessage) packet;
if (result.Result != 0) if (result.Result != 0)
{ {
tcs.SetException(new NpFileException()); tcs.SetException(new NpFileException(result.Result));
return; return;
} }
tcs.SetResult(result.FileData); tcs.SetResult(result.FileData);

View File

@ -7,8 +7,13 @@ namespace NPSharp
{ {
class NpFileException : Exception class NpFileException : Exception
{ {
public NpFileException() internal NpFileException(int error)
:base(@"Could not fetch file from NP server.") : base(error == 1 ? @"File not found on NP server" : @"Internal error on NP server")
{
}
internal NpFileException()
: base(@"Could not fetch file from NP server.")
{ {
} }
} }

14
src/npfile/App.config Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

196
src/npfile/Program.cs Normal file
View File

@ -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/<file>", IPAddress.Any, hport);
log.InfoFormat("Access user files through http://{0}:{1}/user/<file>", 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<Task> 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("<pre><tt><code>{0}</code></tt></pre>", 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<Task> 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("<pre><tt><code>{0}</code></tt></pre>", 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();
}
}
}

View File

@ -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")]

78
src/npfile/npfile.csproj Normal file
View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{19EBF339-E076-4962-A671-5B44A978687D}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NPSharp.CommandLine.File</RootNamespace>
<AssemblyName>npfile</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)\bin\$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\</IntDir>
<IntermediateOutputPath>$(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\</IntermediateOutputPath>
<BaseIntermediateOutputPath>$(SolutionDir)\obj\$(TargetName)\$(Configuration)\$(Platform)\</BaseIntermediateOutputPath>
<OutputPath>$(SolutionDir)\bin\$(Configuration)\$(Platform)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
<Reference Include="uhttpsharp">
<HintPath>..\..\packages\uHttpSharp.0.1.4.7\lib\net40\uhttpsharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libnpsharp\libnpsharp.csproj">
<Project>{1a5ac63a-250e-4bc8-b81a-822ac31f5e37}</Project>
<Name>libnpsharp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.3" targetFramework="net45" />
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
<package id="uHttpSharp" version="0.1.4.7" targetFramework="net45" />
</packages>

View File

@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> </startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration> </configuration>

View File

@ -33,6 +33,7 @@ namespace NPSharp.CommandLine.MOTD
var log = LogManager.GetLogger("Main"); var log = LogManager.GetLogger("Main");
// Arguments
if (args.Length < 4) if (args.Length < 4)
{ {
log.ErrorFormat("Needs 4 arguments: hostname port username password"); log.ErrorFormat("Needs 4 arguments: hostname port username password");

View File

@ -44,7 +44,6 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />