diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/csharp | |
parent | Initial commit. (diff) | |
download | ceph-upstream/16.2.11+ds.tar.xz ceph-upstream/16.2.11+ds.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
98 files changed, 11932 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/csharp/Makefile.am b/src/jaegertracing/thrift/lib/csharp/Makefile.am new file mode 100644 index 000000000..cc2bbc96c --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/Makefile.am @@ -0,0 +1,114 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +SUBDIRS = . test/Multiplex + +THRIFTCODE = \ + src/Collections/THashSet.cs \ + src/Collections/TCollections.cs \ + src/Properties/AssemblyInfo.cs \ + src/Protocol/TAbstractBase.cs \ + src/Protocol/TBase.cs \ + src/Protocol/TBase64Utils.cs \ + src/Protocol/TJSONProtocol.cs \ + src/Protocol/TProtocolException.cs \ + src/Protocol/TProtocolFactory.cs \ + src/Protocol/TList.cs \ + src/Protocol/TSet.cs \ + src/Protocol/TMap.cs \ + src/Protocol/TProtocolUtil.cs \ + src/Protocol/TMessageType.cs \ + src/Protocol/TProtocol.cs \ + src/Protocol/TProtocolDecorator.cs \ + src/Protocol/TMultiplexedProtocol.cs \ + src/Protocol/TMultiplexedProcessor.cs \ + src/Protocol/TType.cs \ + src/Protocol/TField.cs \ + src/Protocol/TMessage.cs \ + src/Protocol/TStruct.cs \ + src/Protocol/TBinaryProtocol.cs \ + src/Protocol/TCompactProtocol.cs \ + src/Server/TThreadedServer.cs \ + src/Server/TThreadPoolServer.cs \ + src/Server/TSimpleServer.cs \ + src/Server/TServer.cs \ + src/Server/TServerEventHandler.cs \ + src/Transport/TBufferedTransport.cs \ + src/Transport/TTransport.cs \ + src/Transport/TSocket.cs \ + src/Transport/TSocketVersionizer.cs \ + src/Transport/TTransportException.cs \ + src/Transport/TStreamTransport.cs \ + src/Transport/TFramedTransport.cs \ + src/Transport/TServerTransport.cs \ + src/Transport/TServerSocket.cs \ + src/Transport/TTransportFactory.cs \ + src/Transport/THttpClient.cs \ + src/Transport/THttpHandler.cs \ + src/Transport/TMemoryBuffer.cs \ + src/Transport/TNamedPipeClientTransport.cs \ + src/Transport/TNamedPipeServerTransport.cs \ + src/Transport/TTLSSocket.cs \ + src/Transport/TTLSServerSocket.cs \ + src/TProcessor.cs \ + src/TProcessorFactory.cs \ + src/TSingletonProcessorFactory.cs \ + src/TPrototypeProcessorFactory.cs \ + src/TControllingHandler.cs \ + src/TException.cs \ + src/TApplicationException.cs + +if MONO_MCS +export CSC = mcs +else +export CSC = gmcs +endif + +if NET_2_0 +export CSC_DEFINES = -d:NET_2_0 +endif + +all-local: Thrift.dll Thrift.45.dll + +Thrift.dll: $(THRIFTCODE) + $(CSC) $(CSC_DEFINES) -out:$@ -target:library -reference:System.Web $(THRIFTCODE) + +Thrift.45.dll: $(THRIFTCODE) + $(CSC) $(CSC_DEFINES) -out:$@ -target:library -reference:System.Web $(THRIFTCODE) + +CLEANFILES = \ + Thrift.dll \ + Thrift.45.dll + +DISTCLEANFILES = \ + Makefile.in + +EXTRA_DIST = \ + $(THRIFTCODE) \ + ThriftMSBuildTask \ + src/Thrift.csproj \ + src/Thrift.45.csproj \ + src/Thrift.sln \ + src/Net35/ExtensionsNet35.cs \ + src/Transport/TSilverlightSocket.cs \ + src/Transport/THttpTaskAsyncHandler.cs \ + src/TAsyncProcessor.cs \ + test \ + coding_standards.md \ + README.md diff --git a/src/jaegertracing/thrift/lib/csharp/README.md b/src/jaegertracing/thrift/lib/csharp/README.md new file mode 100644 index 000000000..5fc14cb3c --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/README.md @@ -0,0 +1,32 @@ +Thrift C# Software Library + +Deprecation notice +======= + +Per [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723), both CSharp and Netcore targets are deprecated +and will be removed with the next release. Migrate to the [NetStd language target](../netstd/README.md) instead. + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +Using Thrift with C# +==================== + +Thrift requires Mono >= 1.2.6 or .NET framework >= 3.5 diff --git a/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6e99dd9fd --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ThriftMSBuildTask")] +[assembly: AssemblyDescription("MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("ThriftMSBuildTask")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +//@TODO where to put License information? + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5095e09d-7b95-4be1-b250-e1c1db1c485e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.*")] +[assembly: AssemblyFileVersion("0.13.0.*")] diff --git a/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs new file mode 100644 index 000000000..4e6d30112 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs @@ -0,0 +1,246 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Build.Tasks; +using System.IO; +using System.Diagnostics; + +namespace ThriftMSBuildTask +{ + /// <summary> + /// MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll + /// </summary> + public class ThriftBuild : Task + { + /// <summary> + /// The full path to the thrift.exe compiler + /// </summary> + [Required] + public ITaskItem ThriftExecutable + { + get; + set; + } + + /// <summary> + /// The full path to a thrift.dll C# library + /// </summary> + [Required] + public ITaskItem ThriftLibrary + { + get; + set; + } + + /// <summary> + /// A direcotry containing .thrift files + /// </summary> + [Required] + public ITaskItem ThriftDefinitionDir + { + get; + set; + } + + /// <summary> + /// The name of the auto-gen and compiled thrift library. It will placed in + /// the same directory as ThriftLibrary + /// </summary> + [Required] + public ITaskItem OutputName + { + get; + set; + } + + /// <summary> + /// The full path to the compiled ThriftLibrary. This allows msbuild tasks to use this + /// output as a variable for use elsewhere. + /// </summary> + [Output] + public ITaskItem ThriftImplementation + { + get { return thriftImpl; } + } + + private ITaskItem thriftImpl; + private const string lastCompilationName = "LAST_COMP_TIMESTAMP"; + + //use the Message Build Task to write something to build log + private void LogMessage(string text, MessageImportance importance) + { + Message m = new Message(); + m.Text = text; + m.Importance = importance.ToString(); + m.BuildEngine = this.BuildEngine; + m.Execute(); + } + + //recursively find .cs files in srcDir, paths should initially be non-null and empty + private void FindSourcesHelper(string srcDir, List<string> paths) + { + string[] files = Directory.GetFiles(srcDir, "*.cs"); + foreach (string f in files) + { + paths.Add(f); + } + string[] dirs = Directory.GetDirectories(srcDir); + foreach (string dir in dirs) + { + FindSourcesHelper(dir, paths); + } + } + + /// <summary> + /// Quote paths with spaces + /// </summary> + private string SafePath(string path) + { + if (path.Contains(' ') && !path.StartsWith("\"")) + { + return "\"" + path + "\""; + } + return path; + } + + private ITaskItem[] FindSources(string srcDir) + { + List<string> files = new List<string>(); + FindSourcesHelper(srcDir, files); + ITaskItem[] items = new ITaskItem[files.Count]; + for (int i = 0; i < items.Length; i++) + { + items[i] = new TaskItem(files[i]); + } + return items; + } + + private string LastWriteTime(string defDir) + { + string[] files = Directory.GetFiles(defDir, "*.thrift"); + DateTime d = (new DirectoryInfo(defDir)).LastWriteTime; + foreach(string file in files) + { + FileInfo f = new FileInfo(file); + DateTime curr = f.LastWriteTime; + if (DateTime.Compare(curr, d) > 0) + { + d = curr; + } + } + return d.ToFileTimeUtc().ToString(); + } + + public override bool Execute() + { + string defDir = SafePath(ThriftDefinitionDir.ItemSpec); + //look for last compilation timestamp + string lastBuildPath = Path.Combine(defDir, lastCompilationName); + DirectoryInfo defDirInfo = new DirectoryInfo(defDir); + string lastWrite = LastWriteTime(defDir); + if (File.Exists(lastBuildPath)) + { + string lastComp = File.ReadAllText(lastBuildPath); + //don't recompile if the thrift library has been updated since lastComp + FileInfo f = new FileInfo(ThriftLibrary.ItemSpec); + string thriftLibTime = f.LastWriteTimeUtc.ToFileTimeUtc().ToString(); + if (lastComp.CompareTo(thriftLibTime) < 0) + { + //new thrift library, do a compile + lastWrite = thriftLibTime; + } + else if (lastComp == lastWrite || (lastComp == thriftLibTime && lastComp.CompareTo(lastWrite) > 0)) + { + //the .thrift dir hasn't been written to since last compilation, don't need to do anything + LogMessage("ThriftImpl up-to-date", MessageImportance.High); + return true; + } + } + + //find the directory of the thriftlibrary (that's where output will go) + FileInfo thriftLibInfo = new FileInfo(SafePath(ThriftLibrary.ItemSpec)); + string thriftDir = thriftLibInfo.Directory.FullName; + + string genDir = Path.Combine(thriftDir, "gen-csharp"); + if (Directory.Exists(genDir)) + { + try + { + Directory.Delete(genDir, true); + } + catch { /*eh i tried, just over-write now*/} + } + + //run the thrift executable to generate C# + foreach (string thriftFile in Directory.GetFiles(defDir, "*.thrift")) + { + LogMessage("Generating code for: " + thriftFile, MessageImportance.Normal); + Process p = new Process(); + p.StartInfo.FileName = SafePath(ThriftExecutable.ItemSpec); + p.StartInfo.Arguments = "--gen csharp -o " + SafePath(thriftDir) + " -r " + thriftFile; + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = false; + p.Start(); + p.WaitForExit(); + if (p.ExitCode != 0) + { + LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); + return false; + } + if (p.ExitCode != 0) + { + LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); + return false; + } + } + + Csc csc = new Csc(); + csc.TargetType = "library"; + csc.References = new ITaskItem[] { new TaskItem(ThriftLibrary.ItemSpec) }; + csc.EmitDebugInformation = true; + string outputPath = Path.Combine(thriftDir, OutputName.ItemSpec); + csc.OutputAssembly = new TaskItem(outputPath); + csc.Sources = FindSources(Path.Combine(thriftDir, "gen-csharp")); + csc.BuildEngine = this.BuildEngine; + LogMessage("Compiling generated cs...", MessageImportance.Normal); + if (!csc.Execute()) + { + return false; + } + + //write file to defDir to indicate a build was successfully completed + File.WriteAllText(lastBuildPath, lastWrite); + + thriftImpl = new TaskItem(outputPath); + + return true; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj new file mode 100644 index 000000000..f4a26de45 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{EC0A0231-66EA-4593-A792-C6CA3BB8668E}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ThriftMSBuildTask</RootNamespace> + <AssemblyName>ThriftMSBuildTask</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>0.13.0.0</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.Build.Framework" /> + <Reference Include="Microsoft.Build.Tasks" /> + <Reference Include="Microsoft.Build.Utilities" /> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ThriftBuild.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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> diff --git a/src/jaegertracing/thrift/lib/csharp/coding_standards.md b/src/jaegertracing/thrift/lib/csharp/coding_standards.md new file mode 100644 index 000000000..dc87190bf --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/coding_standards.md @@ -0,0 +1,6 @@ +## C# Coding Standards + +Please follow: + * [Thrift General Coding Standards](/doc/coding_standards.md) + * [MSDN C# Coding Conventions](http://msdn.microsoft.com/en-us/library/ff926074.aspx) + * [C# Coding Guidelines](http://csharpguidelines.codeplex.com/) diff --git a/src/jaegertracing/thrift/lib/csharp/src/Collections/TCollections.cs b/src/jaegertracing/thrift/lib/csharp/src/Collections/TCollections.cs new file mode 100644 index 000000000..84afb6a62 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Collections/TCollections.cs @@ -0,0 +1,94 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +using System; +using System.Collections; + +namespace Thrift.Collections +{ + public class TCollections + { + /// <summary> + /// This will return true if the two collections are value-wise the same. + /// If the collection contains a collection, the collections will be compared using this method. + /// </summary> + public static bool Equals (IEnumerable first, IEnumerable second) + { + if (first == null && second == null) + { + return true; + } + if (first == null || second == null) + { + return false; + } + IEnumerator fiter = first.GetEnumerator (); + IEnumerator siter = second.GetEnumerator (); + + bool fnext = fiter.MoveNext (); + bool snext = siter.MoveNext (); + while (fnext && snext) + { + IEnumerable fenum = fiter.Current as IEnumerable; + IEnumerable senum = siter.Current as IEnumerable; + if (fenum != null && senum != null) + { + if (!Equals(fenum, senum)) + { + return false; + } + } + else if (fenum == null ^ senum == null) + { + return false; + } + else if (!Equals(fiter.Current, siter.Current)) + { + return false; + } + fnext = fiter.MoveNext(); + snext = siter.MoveNext(); + } + + return fnext == snext; + } + + /// <summary> + /// This returns a hashcode based on the value of the enumerable. + /// </summary> + public static int GetHashCode (IEnumerable enumerable) + { + if (enumerable == null) + { + return 0; + } + + int hashcode = 0; + foreach (object obj in enumerable) + { + IEnumerable enum2 = obj as IEnumerable; + int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2); + unchecked + { + hashcode = (hashcode * 397) ^ (objHash); + } + } + return hashcode; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Collections/THashSet.cs b/src/jaegertracing/thrift/lib/csharp/src/Collections/THashSet.cs new file mode 100644 index 000000000..e29271a93 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Collections/THashSet.cs @@ -0,0 +1,160 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections; +using System.Collections.Generic; + +#if SILVERLIGHT +using System.Runtime.Serialization; +#endif + +namespace Thrift.Collections +{ +#if SILVERLIGHT + [DataContract] +#else + [Serializable] +#endif + public class THashSet<T> : ICollection<T> + { +#if NET_2_0 || SILVERLIGHT +#if SILVERLIGHT + [DataMember] +#endif + TDictSet<T> set = new TDictSet<T>(); +#else + HashSet<T> set = new HashSet<T>(); +#endif + public int Count + { + get { return set.Count; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public void Add(T item) + { + set.Add(item); + } + + public void Clear() + { + set.Clear(); + } + + public bool Contains(T item) + { + return set.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + set.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return set.GetEnumerator(); + } + + IEnumerator<T> IEnumerable<T>.GetEnumerator() + { + return ((IEnumerable<T>)set).GetEnumerator(); + } + + public bool Remove(T item) + { + return set.Remove(item); + } + +#if NET_2_0 || SILVERLIGHT +#if SILVERLIGHT + [DataContract] +#endif + private class TDictSet<V> : ICollection<V> + { +#if SILVERLIGHT + [DataMember] +#endif + Dictionary<V, TDictSet<V>> dict = new Dictionary<V, TDictSet<V>>(); + + public int Count + { + get { return dict.Count; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public IEnumerator GetEnumerator() + { + return ((IEnumerable)dict.Keys).GetEnumerator(); + } + + IEnumerator<V> IEnumerable<V>.GetEnumerator() + { + return dict.Keys.GetEnumerator(); + } + + public bool Add(V item) + { + if (!dict.ContainsKey(item)) + { + dict[item] = this; + return true; + } + + return false; + } + + void ICollection<V>.Add(V item) + { + Add(item); + } + + public void Clear() + { + dict.Clear(); + } + + public bool Contains(V item) + { + return dict.ContainsKey(item); + } + + public void CopyTo(V[] array, int arrayIndex) + { + dict.Keys.CopyTo(array, arrayIndex); + } + + public bool Remove(V item) + { + return dict.Remove(item); + } + } +#endif + } + +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Net35/ExtensionsNet35.cs b/src/jaegertracing/thrift/lib/csharp/src/Net35/ExtensionsNet35.cs new file mode 100644 index 000000000..73a423288 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Net35/ExtensionsNet35.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +#if (!NET45) +namespace Thrift +{ + static class StreamExtensionsNet35 + { + // CopyTo() has been added in 4.0 + public static long CopyTo(this Stream source, Stream target) + { + byte[] buffer = new byte[8192]; // multiple of 4096 + long nTotal = 0; + while (true) + { + int nRead = source.Read(buffer, 0, buffer.Length); + if (nRead <= 0) // done? + return nTotal; + + target.Write(buffer, 0, nRead); + nTotal += nRead; + } + } + } + +} +#endif + diff --git a/src/jaegertracing/thrift/lib/csharp/src/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/src/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ace031045 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Thrift")] +[assembly: AssemblyDescription("C# bindings for the Apache Thrift RPC system")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +//@TODO where to put License information? + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TAbstractBase.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TAbstractBase.cs new file mode 100644 index 000000000..f5a61cd44 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TAbstractBase.cs @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +namespace Thrift.Protocol +{ + public interface TAbstractBase + { + /// <summary> + /// Writes the objects out to the protocol. + /// </summary> + void Write(TProtocol tProtocol); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase.cs new file mode 100644 index 000000000..411e4d95f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase.cs @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +namespace Thrift.Protocol +{ + public interface TBase : TAbstractBase + { + /// <summary> + /// Reads the TObject from the given input protocol. + /// </summary> + void Read(TProtocol tProtocol); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase64Utils.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase64Utils.cs new file mode 100644 index 000000000..9eaaebdda --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBase64Utils.cs @@ -0,0 +1,100 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; + +namespace Thrift.Protocol +{ + internal static class TBase64Utils + { + internal const string ENCODE_TABLE = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + internal static void encode(byte[] src, int srcOff, int len, byte[] dst, + int dstOff) + { + dst[dstOff] = (byte)ENCODE_TABLE[(src[srcOff] >> 2) & 0x3F]; + if (len == 3) + { + dst[dstOff + 1] = + (byte)ENCODE_TABLE[ + ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = + (byte)ENCODE_TABLE[ + ((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; + dst[dstOff + 3] = + (byte)ENCODE_TABLE[src[srcOff + 2] & 0x3F]; + } + else if (len == 2) + { + dst[dstOff + 1] = + (byte)ENCODE_TABLE[ + ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = + (byte)ENCODE_TABLE[(src[srcOff + 1] << 2) & 0x3C]; + + } + else + { // len == 1) { + dst[dstOff + 1] = + (byte)ENCODE_TABLE[(src[srcOff] << 4) & 0x30]; + } + } + + private static int[] DECODE_TABLE = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + }; + + internal static void decode(byte[] src, int srcOff, int len, byte[] dst, + int dstOff) + { + dst[dstOff] = (byte) + ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) | + (DECODE_TABLE[src[srcOff + 1] & 0x0FF] >> 4)); + if (len > 2) + { + dst[dstOff + 1] = (byte) + (((DECODE_TABLE[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | + (DECODE_TABLE[src[srcOff + 2] & 0x0FF] >> 2)); + if (len > 3) + { + dst[dstOff + 2] = (byte) + (((DECODE_TABLE[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | + DECODE_TABLE[src[srcOff + 3] & 0x0FF]); + } + } + } + + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBinaryProtocol.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBinaryProtocol.cs new file mode 100644 index 000000000..a4faa946f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TBinaryProtocol.cs @@ -0,0 +1,395 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + public class TBinaryProtocol : TProtocol + { + protected const uint VERSION_MASK = 0xffff0000; + protected const uint VERSION_1 = 0x80010000; + + protected bool strictRead_ = false; + protected bool strictWrite_ = true; + + #region BinaryProtocol Factory + + public class Factory : TProtocolFactory + { + protected bool strictRead_ = false; + protected bool strictWrite_ = true; + + public Factory() + : this(false, true) + { + } + + public Factory(bool strictRead, bool strictWrite) + { + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + public TProtocol GetProtocol(TTransport trans) + { + return new TBinaryProtocol(trans, strictRead_, strictWrite_); + } + } + + #endregion + + public TBinaryProtocol(TTransport trans) + : this(trans, false, true) + { + } + + public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) + : base(trans) + { + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + #region Write Methods + + public override void WriteMessageBegin(TMessage message) + { + if (strictWrite_) + { + uint version = VERSION_1 | (uint)(message.Type); + WriteI32((int)version); + WriteString(message.Name); + WriteI32(message.SeqID); + } + else + { + WriteString(message.Name); + WriteByte((sbyte)message.Type); + WriteI32(message.SeqID); + } + } + + public override void WriteMessageEnd() + { + } + + public override void WriteStructBegin(TStruct struc) + { + } + + public override void WriteStructEnd() + { + } + + public override void WriteFieldBegin(TField field) + { + WriteByte((sbyte)field.Type); + WriteI16(field.ID); + } + + public override void WriteFieldEnd() + { + } + + public override void WriteFieldStop() + { + WriteByte((sbyte)TType.Stop); + } + + public override void WriteMapBegin(TMap map) + { + WriteByte((sbyte)map.KeyType); + WriteByte((sbyte)map.ValueType); + WriteI32(map.Count); + } + + public override void WriteMapEnd() + { + } + + public override void WriteListBegin(TList list) + { + WriteByte((sbyte)list.ElementType); + WriteI32(list.Count); + } + + public override void WriteListEnd() + { + } + + public override void WriteSetBegin(TSet set) + { + WriteByte((sbyte)set.ElementType); + WriteI32(set.Count); + } + + public override void WriteSetEnd() + { + } + + public override void WriteBool(bool b) + { + WriteByte(b ? (sbyte)1 : (sbyte)0); + } + + private byte[] bout = new byte[1]; + public override void WriteByte(sbyte b) + { + bout[0] = (byte)b; + trans.Write(bout, 0, 1); + } + + private byte[] i16out = new byte[2]; + public override void WriteI16(short s) + { + i16out[0] = (byte)(0xff & (s >> 8)); + i16out[1] = (byte)(0xff & s); + trans.Write(i16out, 0, 2); + } + + private byte[] i32out = new byte[4]; + public override void WriteI32(int i32) + { + i32out[0] = (byte)(0xff & (i32 >> 24)); + i32out[1] = (byte)(0xff & (i32 >> 16)); + i32out[2] = (byte)(0xff & (i32 >> 8)); + i32out[3] = (byte)(0xff & i32); + trans.Write(i32out, 0, 4); + } + + private byte[] i64out = new byte[8]; + public override void WriteI64(long i64) + { + i64out[0] = (byte)(0xff & (i64 >> 56)); + i64out[1] = (byte)(0xff & (i64 >> 48)); + i64out[2] = (byte)(0xff & (i64 >> 40)); + i64out[3] = (byte)(0xff & (i64 >> 32)); + i64out[4] = (byte)(0xff & (i64 >> 24)); + i64out[5] = (byte)(0xff & (i64 >> 16)); + i64out[6] = (byte)(0xff & (i64 >> 8)); + i64out[7] = (byte)(0xff & i64); + trans.Write(i64out, 0, 8); + } + + public override void WriteDouble(double d) + { +#if !SILVERLIGHT + WriteI64(BitConverter.DoubleToInt64Bits(d)); +#else + var bytes = BitConverter.GetBytes(d); + WriteI64(BitConverter.ToInt64(bytes, 0)); +#endif + } + + public override void WriteBinary(byte[] b) + { + WriteI32(b.Length); + trans.Write(b, 0, b.Length); + } + + #endregion + + #region ReadMethods + + public override TMessage ReadMessageBegin() + { + TMessage message = new TMessage(); + int size = ReadI32(); + if (size < 0) + { + uint version = (uint)size & VERSION_MASK; + if (version != VERSION_1) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version); + } + message.Type = (TMessageType)(size & 0x000000ff); + message.Name = ReadString(); + message.SeqID = ReadI32(); + } + else + { + if (strictRead_) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); + } + message.Name = ReadStringBody(size); + message.Type = (TMessageType)ReadByte(); + message.SeqID = ReadI32(); + } + return message; + } + + public override void ReadMessageEnd() + { + } + + public override TStruct ReadStructBegin() + { + return new TStruct(); + } + + public override void ReadStructEnd() + { + } + + public override TField ReadFieldBegin() + { + TField field = new TField(); + field.Type = (TType)ReadByte(); + + if (field.Type != TType.Stop) + { + field.ID = ReadI16(); + } + + return field; + } + + public override void ReadFieldEnd() + { + } + + public override TMap ReadMapBegin() + { + TMap map = new TMap(); + map.KeyType = (TType)ReadByte(); + map.ValueType = (TType)ReadByte(); + map.Count = ReadI32(); + + return map; + } + + public override void ReadMapEnd() + { + } + + public override TList ReadListBegin() + { + TList list = new TList(); + list.ElementType = (TType)ReadByte(); + list.Count = ReadI32(); + + return list; + } + + public override void ReadListEnd() + { + } + + public override TSet ReadSetBegin() + { + TSet set = new TSet(); + set.ElementType = (TType)ReadByte(); + set.Count = ReadI32(); + + return set; + } + + public override void ReadSetEnd() + { + } + + public override bool ReadBool() + { + return ReadByte() == 1; + } + + private byte[] bin = new byte[1]; + public override sbyte ReadByte() + { + ReadAll(bin, 0, 1); + return (sbyte)bin[0]; + } + + private byte[] i16in = new byte[2]; + public override short ReadI16() + { + ReadAll(i16in, 0, 2); + return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff))); + } + + private byte[] i32in = new byte[4]; + public override int ReadI32() + { + ReadAll(i32in, 0, 4); + return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff))); + } + +#pragma warning disable 675 + + private byte[] i64in = new byte[8]; + public override long ReadI64() + { + ReadAll(i64in, 0, 8); + unchecked + { + return (long)( + ((long)(i64in[0] & 0xff) << 56) | + ((long)(i64in[1] & 0xff) << 48) | + ((long)(i64in[2] & 0xff) << 40) | + ((long)(i64in[3] & 0xff) << 32) | + ((long)(i64in[4] & 0xff) << 24) | + ((long)(i64in[5] & 0xff) << 16) | + ((long)(i64in[6] & 0xff) << 8) | + ((long)(i64in[7] & 0xff))); + } + } + +#pragma warning restore 675 + + public override double ReadDouble() + { +#if !SILVERLIGHT + return BitConverter.Int64BitsToDouble(ReadI64()); +#else + var value = ReadI64(); + var bytes = BitConverter.GetBytes(value); + return BitConverter.ToDouble(bytes, 0); +#endif + } + + public override byte[] ReadBinary() + { + int size = ReadI32(); + byte[] buf = new byte[size]; + trans.ReadAll(buf, 0, size); + return buf; + } + private string ReadStringBody(int size) + { + byte[] buf = new byte[size]; + trans.ReadAll(buf, 0, size); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + private int ReadAll(byte[] buf, int off, int len) + { + return trans.ReadAll(buf, off, len); + } + + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TCompactProtocol.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TCompactProtocol.cs new file mode 100644 index 000000000..ff673975e --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TCompactProtocol.cs @@ -0,0 +1,849 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; +using System.Collections; +using System.IO; +using System.Collections.Generic; + +namespace Thrift.Protocol +{ + public class TCompactProtocol : TProtocol + { + private static TStruct ANONYMOUS_STRUCT = new TStruct(""); + private static TField TSTOP = new TField("", TType.Stop, (short)0); + + private static byte[] ttypeToCompactType = new byte[16]; + + private const byte PROTOCOL_ID = 0x82; + private const byte VERSION = 1; + private const byte VERSION_MASK = 0x1f; // 0001 1111 + private const byte TYPE_MASK = 0xE0; // 1110 0000 + private const byte TYPE_BITS = 0x07; // 0000 0111 + private const int TYPE_SHIFT_AMOUNT = 5; + + /// <summary> + /// All of the on-wire type codes. + /// </summary> + private static class Types + { + public const byte STOP = 0x00; + public const byte BOOLEAN_TRUE = 0x01; + public const byte BOOLEAN_FALSE = 0x02; + public const byte BYTE = 0x03; + public const byte I16 = 0x04; + public const byte I32 = 0x05; + public const byte I64 = 0x06; + public const byte DOUBLE = 0x07; + public const byte BINARY = 0x08; + public const byte LIST = 0x09; + public const byte SET = 0x0A; + public const byte MAP = 0x0B; + public const byte STRUCT = 0x0C; + } + + /// <summary> + /// Used to keep track of the last field for the current and previous structs, + /// so we can do the delta stuff. + /// </summary> + private Stack<short> lastField_ = new Stack<short>(15); + + private short lastFieldId_ = 0; + + /// <summary> + /// If we encounter a boolean field begin, save the TField here so it can + /// have the value incorporated. + /// </summary> + private Nullable<TField> booleanField_; + + /// <summary> + /// If we Read a field header, and it's a boolean field, save the boolean + /// value here so that ReadBool can use it. + /// </summary> + private Nullable<Boolean> boolValue_; + + + #region CompactProtocol Factory + + public class Factory : TProtocolFactory + { + public Factory() { } + + public TProtocol GetProtocol(TTransport trans) + { + return new TCompactProtocol(trans); + } + } + + #endregion + + public TCompactProtocol(TTransport trans) + : base(trans) + { + ttypeToCompactType[(int)TType.Stop] = Types.STOP; + ttypeToCompactType[(int)TType.Bool] = Types.BOOLEAN_TRUE; + ttypeToCompactType[(int)TType.Byte] = Types.BYTE; + ttypeToCompactType[(int)TType.I16] = Types.I16; + ttypeToCompactType[(int)TType.I32] = Types.I32; + ttypeToCompactType[(int)TType.I64] = Types.I64; + ttypeToCompactType[(int)TType.Double] = Types.DOUBLE; + ttypeToCompactType[(int)TType.String] = Types.BINARY; + ttypeToCompactType[(int)TType.List] = Types.LIST; + ttypeToCompactType[(int)TType.Set] = Types.SET; + ttypeToCompactType[(int)TType.Map] = Types.MAP; + ttypeToCompactType[(int)TType.Struct] = Types.STRUCT; + } + + public void reset() + { + lastField_.Clear(); + lastFieldId_ = 0; + } + + #region Write Methods + + /// <summary> + /// Writes a byte without any possibility of all that field header nonsense. + /// Used internally by other writing methods that know they need to Write a byte. + /// </summary> + private byte[] byteDirectBuffer = new byte[1]; + + private void WriteByteDirect(byte b) + { + byteDirectBuffer[0] = b; + trans.Write(byteDirectBuffer); + } + + /// <summary> + /// Writes a byte without any possibility of all that field header nonsense. + /// </summary> + private void WriteByteDirect(int n) + { + WriteByteDirect((byte)n); + } + + /// <summary> + /// Write an i32 as a varint. Results in 1-5 bytes on the wire. + /// TODO: make a permanent buffer like WriteVarint64? + /// </summary> + byte[] i32buf = new byte[5]; + + private void WriteVarint32(uint n) + { + int idx = 0; + while (true) + { + if ((n & ~0x7F) == 0) + { + i32buf[idx++] = (byte)n; + // WriteByteDirect((byte)n); + break; + // return; + } + else + { + i32buf[idx++] = (byte)((n & 0x7F) | 0x80); + // WriteByteDirect((byte)((n & 0x7F) | 0x80)); + n >>= 7; + } + } + trans.Write(i32buf, 0, idx); + } + + /// <summary> + /// Write a message header to the wire. Compact Protocol messages contain the + /// protocol version so we can migrate forwards in the future if need be. + /// </summary> + public override void WriteMessageBegin(TMessage message) + { + WriteByteDirect(PROTOCOL_ID); + WriteByteDirect((byte)((VERSION & VERSION_MASK) | ((((uint)message.Type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK))); + WriteVarint32((uint)message.SeqID); + WriteString(message.Name); + } + + /// <summary> + /// Write a struct begin. This doesn't actually put anything on the wire. We + /// use it as an opportunity to put special placeholder markers on the field + /// stack so we can get the field id deltas correct. + /// </summary> + public override void WriteStructBegin(TStruct strct) + { + lastField_.Push(lastFieldId_); + lastFieldId_ = 0; + } + + /// <summary> + /// Write a struct end. This doesn't actually put anything on the wire. We use + /// this as an opportunity to pop the last field from the current struct off + /// of the field stack. + /// </summary> + public override void WriteStructEnd() + { + lastFieldId_ = lastField_.Pop(); + } + + /// <summary> + /// Write a field header containing the field id and field type. If the + /// difference between the current field id and the last one is small (< 15), + /// then the field id will be encoded in the 4 MSB as a delta. Otherwise, the + /// field id will follow the type header as a zigzag varint. + /// </summary> + public override void WriteFieldBegin(TField field) + { + if (field.Type == TType.Bool) + { + // we want to possibly include the value, so we'll wait. + booleanField_ = field; + } + else + { + WriteFieldBeginInternal(field, 0xFF); + } + } + + /// <summary> + /// The workhorse of WriteFieldBegin. It has the option of doing a + /// 'type override' of the type header. This is used specifically in the + /// boolean field case. + /// </summary> + private void WriteFieldBeginInternal(TField field, byte typeOverride) + { + // short lastField = lastField_.Pop(); + + // if there's a type override, use that. + byte typeToWrite = typeOverride == 0xFF ? getCompactType(field.Type) : typeOverride; + + // check if we can use delta encoding for the field id + if (field.ID > lastFieldId_ && field.ID - lastFieldId_ <= 15) + { + // Write them together + WriteByteDirect((field.ID - lastFieldId_) << 4 | typeToWrite); + } + else + { + // Write them separate + WriteByteDirect(typeToWrite); + WriteI16(field.ID); + } + + lastFieldId_ = field.ID; + // lastField_.push(field.id); + } + + /// <summary> + /// Write the STOP symbol so we know there are no more fields in this struct. + /// </summary> + public override void WriteFieldStop() + { + WriteByteDirect(Types.STOP); + } + + /// <summary> + /// Write a map header. If the map is empty, omit the key and value type + /// headers, as we don't need any additional information to skip it. + /// </summary> + public override void WriteMapBegin(TMap map) + { + if (map.Count == 0) + { + WriteByteDirect(0); + } + else + { + WriteVarint32((uint)map.Count); + WriteByteDirect(getCompactType(map.KeyType) << 4 | getCompactType(map.ValueType)); + } + } + + /// <summary> + /// Write a list header. + /// </summary> + public override void WriteListBegin(TList list) + { + WriteCollectionBegin(list.ElementType, list.Count); + } + + /// <summary> + /// Write a set header. + /// </summary> + public override void WriteSetBegin(TSet set) + { + WriteCollectionBegin(set.ElementType, set.Count); + } + + /// <summary> + /// Write a boolean value. Potentially, this could be a boolean field, in + /// which case the field header info isn't written yet. If so, decide what the + /// right type header is for the value and then Write the field header. + /// Otherwise, Write a single byte. + /// </summary> + public override void WriteBool(Boolean b) + { + if (booleanField_ != null) + { + // we haven't written the field header yet + WriteFieldBeginInternal(booleanField_.Value, b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); + booleanField_ = null; + } + else + { + // we're not part of a field, so just Write the value. + WriteByteDirect(b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); + } + } + + /// <summary> + /// Write a byte. Nothing to see here! + /// </summary> + public override void WriteByte(sbyte b) + { + WriteByteDirect((byte)b); + } + + /// <summary> + /// Write an I16 as a zigzag varint. + /// </summary> + public override void WriteI16(short i16) + { + WriteVarint32(intToZigZag(i16)); + } + + /// <summary> + /// Write an i32 as a zigzag varint. + /// </summary> + public override void WriteI32(int i32) + { + WriteVarint32(intToZigZag(i32)); + } + + /// <summary> + /// Write an i64 as a zigzag varint. + /// </summary> + public override void WriteI64(long i64) + { + WriteVarint64(longToZigzag(i64)); + } + + /// <summary> + /// Write a double to the wire as 8 bytes. + /// </summary> + public override void WriteDouble(double dub) + { + byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; + fixedLongToBytes(BitConverter.DoubleToInt64Bits(dub), data, 0); + trans.Write(data); + } + + /// <summary> + /// Write a string to the wire with a varint size preceding. + /// </summary> + public override void WriteString(string str) + { + byte[] bytes = UTF8Encoding.UTF8.GetBytes(str); + WriteBinary(bytes, 0, bytes.Length); + } + + /// <summary> + /// Write a byte array, using a varint for the size. + /// </summary> + public override void WriteBinary(byte[] bin) + { + WriteBinary(bin, 0, bin.Length); + } + + private void WriteBinary(byte[] buf, int offset, int length) + { + WriteVarint32((uint)length); + trans.Write(buf, offset, length); + } + + // + // These methods are called by structs, but don't actually have any wire + // output or purpose. + // + + public override void WriteMessageEnd() { } + public override void WriteMapEnd() { } + public override void WriteListEnd() { } + public override void WriteSetEnd() { } + public override void WriteFieldEnd() { } + + // + // Internal writing methods + // + + /// <summary> + /// Abstract method for writing the start of lists and sets. List and sets on + /// the wire differ only by the type indicator. + /// </summary> + protected void WriteCollectionBegin(TType elemType, int size) + { + if (size <= 14) + { + WriteByteDirect(size << 4 | getCompactType(elemType)); + } + else + { + WriteByteDirect(0xf0 | getCompactType(elemType)); + WriteVarint32((uint)size); + } + } + + /// <summary> + /// Write an i64 as a varint. Results in 1-10 bytes on the wire. + /// </summary> + byte[] varint64out = new byte[10]; + private void WriteVarint64(ulong n) + { + int idx = 0; + while (true) + { + if ((n & ~(ulong)0x7FL) == 0) + { + varint64out[idx++] = (byte)n; + break; + } + else + { + varint64out[idx++] = ((byte)((n & 0x7F) | 0x80)); + n >>= 7; + } + } + trans.Write(varint64out, 0, idx); + } + + /// <summary> + /// Convert l into a zigzag long. This allows negative numbers to be + /// represented compactly as a varint. + /// </summary> + private ulong longToZigzag(long n) + { + return (ulong)(n << 1) ^ (ulong)(n >> 63); + } + + /// <summary> + /// Convert n into a zigzag int. This allows negative numbers to be + /// represented compactly as a varint. + /// </summary> + private uint intToZigZag(int n) + { + return (uint)(n << 1) ^ (uint)(n >> 31); + } + + /// <summary> + /// Convert a long into little-endian bytes in buf starting at off and going + /// until off+7. + /// </summary> + private void fixedLongToBytes(long n, byte[] buf, int off) + { + buf[off + 0] = (byte)(n & 0xff); + buf[off + 1] = (byte)((n >> 8) & 0xff); + buf[off + 2] = (byte)((n >> 16) & 0xff); + buf[off + 3] = (byte)((n >> 24) & 0xff); + buf[off + 4] = (byte)((n >> 32) & 0xff); + buf[off + 5] = (byte)((n >> 40) & 0xff); + buf[off + 6] = (byte)((n >> 48) & 0xff); + buf[off + 7] = (byte)((n >> 56) & 0xff); + } + + #endregion + + #region ReadMethods + + /// <summary> + /// Read a message header. + /// </summary> + public override TMessage ReadMessageBegin() + { + byte protocolId = (byte)ReadByte(); + if (protocolId != PROTOCOL_ID) + { + throw new TProtocolException("Expected protocol id " + PROTOCOL_ID.ToString("X") + " but got " + protocolId.ToString("X")); + } + byte versionAndType = (byte)ReadByte(); + byte version = (byte)(versionAndType & VERSION_MASK); + if (version != VERSION) + { + throw new TProtocolException("Expected version " + VERSION + " but got " + version); + } + byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); + int seqid = (int)ReadVarint32(); + string messageName = ReadString(); + return new TMessage(messageName, (TMessageType)type, seqid); + } + + /// <summary> + /// Read a struct begin. There's nothing on the wire for this, but it is our + /// opportunity to push a new struct begin marker onto the field stack. + /// </summary> + public override TStruct ReadStructBegin() + { + lastField_.Push(lastFieldId_); + lastFieldId_ = 0; + return ANONYMOUS_STRUCT; + } + + /// <summary> + /// Doesn't actually consume any wire data, just removes the last field for + /// this struct from the field stack. + /// </summary> + public override void ReadStructEnd() + { + // consume the last field we Read off the wire. + lastFieldId_ = lastField_.Pop(); + } + + /// <summary> + /// Read a field header off the wire. + /// </summary> + public override TField ReadFieldBegin() + { + byte type = (byte)ReadByte(); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == Types.STOP) + { + return TSTOP; + } + + short fieldId; + + // mask off the 4 MSB of the type header. it could contain a field id delta. + short modifier = (short)((type & 0xf0) >> 4); + if (modifier == 0) + { + // not a delta. look ahead for the zigzag varint field id. + fieldId = ReadI16(); + } + else + { + // has a delta. add the delta to the last Read field id. + fieldId = (short)(lastFieldId_ + modifier); + } + + TField field = new TField("", getTType((byte)(type & 0x0f)), fieldId); + + // if this happens to be a boolean field, the value is encoded in the type + if (isBoolType(type)) + { + // save the boolean value in a special instance variable. + boolValue_ = (byte)(type & 0x0f) == Types.BOOLEAN_TRUE ? true : false; + } + + // push the new field onto the field stack so we can keep the deltas going. + lastFieldId_ = field.ID; + return field; + } + + /// <summary> + /// Read a map header off the wire. If the size is zero, skip Reading the key + /// and value type. This means that 0-length maps will yield TMaps without the + /// "correct" types. + /// </summary> + public override TMap ReadMapBegin() + { + int size = (int)ReadVarint32(); + byte keyAndValueType = size == 0 ? (byte)0 : (byte)ReadByte(); + return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size); + } + + /// <summary> + /// Read a list header off the wire. If the list size is 0-14, the size will + /// be packed into the element type header. If it's a longer list, the 4 MSB + /// of the element type header will be 0xF, and a varint will follow with the + /// true size. + /// </summary> + public override TList ReadListBegin() + { + byte size_and_type = (byte)ReadByte(); + int size = (size_and_type >> 4) & 0x0f; + if (size == 15) + { + size = (int)ReadVarint32(); + } + TType type = getTType(size_and_type); + return new TList(type, size); + } + + /// <summary> + /// Read a set header off the wire. If the set size is 0-14, the size will + /// be packed into the element type header. If it's a longer set, the 4 MSB + /// of the element type header will be 0xF, and a varint will follow with the + /// true size. + /// </summary> + public override TSet ReadSetBegin() + { + return new TSet(ReadListBegin()); + } + + /// <summary> + /// Read a boolean off the wire. If this is a boolean field, the value should + /// already have been Read during ReadFieldBegin, so we'll just consume the + /// pre-stored value. Otherwise, Read a byte. + /// </summary> + public override Boolean ReadBool() + { + if (boolValue_ != null) + { + bool result = boolValue_.Value; + boolValue_ = null; + return result; + } + return ReadByte() == Types.BOOLEAN_TRUE; + } + + byte[] byteRawBuf = new byte[1]; + /// <summary> + /// Read a single byte off the wire. Nothing interesting here. + /// </summary> + public override sbyte ReadByte() + { + trans.ReadAll(byteRawBuf, 0, 1); + return (sbyte)byteRawBuf[0]; + } + + /// <summary> + /// Read an i16 from the wire as a zigzag varint. + /// </summary> + public override short ReadI16() + { + return (short)zigzagToInt(ReadVarint32()); + } + + /// <summary> + /// Read an i32 from the wire as a zigzag varint. + /// </summary> + public override int ReadI32() + { + return zigzagToInt(ReadVarint32()); + } + + /// <summary> + /// Read an i64 from the wire as a zigzag varint. + /// </summary> + public override long ReadI64() + { + return zigzagToLong(ReadVarint64()); + } + + /// <summary> + /// No magic here - just Read a double off the wire. + /// </summary> + public override double ReadDouble() + { + byte[] longBits = new byte[8]; + trans.ReadAll(longBits, 0, 8); + return BitConverter.Int64BitsToDouble(bytesToLong(longBits)); + } + + /// <summary> + /// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. + /// </summary> + public override string ReadString() + { + int length = (int)ReadVarint32(); + + if (length == 0) + { + return ""; + } + + return Encoding.UTF8.GetString(ReadBinary(length)); + } + + /// <summary> + /// Read a byte[] from the wire. + /// </summary> + public override byte[] ReadBinary() + { + int length = (int)ReadVarint32(); + if (length == 0) return new byte[0]; + + byte[] buf = new byte[length]; + trans.ReadAll(buf, 0, length); + return buf; + } + + /// <summary> + /// Read a byte[] of a known length from the wire. + /// </summary> + private byte[] ReadBinary(int length) + { + if (length == 0) return new byte[0]; + + byte[] buf = new byte[length]; + trans.ReadAll(buf, 0, length); + return buf; + } + + // + // These methods are here for the struct to call, but don't have any wire + // encoding. + // + public override void ReadMessageEnd() { } + public override void ReadFieldEnd() { } + public override void ReadMapEnd() { } + public override void ReadListEnd() { } + public override void ReadSetEnd() { } + + // + // Internal Reading methods + // + + /// <summary> + /// Read an i32 from the wire as a varint. The MSB of each byte is set + /// if there is another byte to follow. This can Read up to 5 bytes. + /// </summary> + private uint ReadVarint32() + { + uint result = 0; + int shift = 0; + while (true) + { + byte b = (byte)ReadByte(); + result |= (uint)(b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + } + return result; + } + + /// <summary> + /// Read an i64 from the wire as a proper varint. The MSB of each byte is set + /// if there is another byte to follow. This can Read up to 10 bytes. + /// </summary> + private ulong ReadVarint64() + { + int shift = 0; + ulong result = 0; + while (true) + { + byte b = (byte)ReadByte(); + result |= (ulong)(b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + } + + return result; + } + + #endregion + + // + // encoding helpers + // + + /// <summary> + /// Convert from zigzag int to int. + /// </summary> + private int zigzagToInt(uint n) + { + return (int)(n >> 1) ^ (-(int)(n & 1)); + } + + /// <summary> + /// Convert from zigzag long to long. + /// </summary> + private long zigzagToLong(ulong n) + { + return (long)(n >> 1) ^ (-(long)(n & 1)); + } + + /// <summary> + /// Note that it's important that the mask bytes are long literals, + /// otherwise they'll default to ints, and when you shift an int left 56 bits, + /// you just get a messed up int. + /// </summary> + private long bytesToLong(byte[] bytes) + { + return + ((bytes[7] & 0xffL) << 56) | + ((bytes[6] & 0xffL) << 48) | + ((bytes[5] & 0xffL) << 40) | + ((bytes[4] & 0xffL) << 32) | + ((bytes[3] & 0xffL) << 24) | + ((bytes[2] & 0xffL) << 16) | + ((bytes[1] & 0xffL) << 8) | + ((bytes[0] & 0xffL)); + } + + // + // type testing and converting + // + + private Boolean isBoolType(byte b) + { + int lowerNibble = b & 0x0f; + return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE; + } + + /// <summary> + /// Given a TCompactProtocol.Types constant, convert it to its corresponding + /// TType value. + /// </summary> + private TType getTType(byte type) + { + switch ((byte)(type & 0x0f)) + { + case Types.STOP: + return TType.Stop; + case Types.BOOLEAN_FALSE: + case Types.BOOLEAN_TRUE: + return TType.Bool; + case Types.BYTE: + return TType.Byte; + case Types.I16: + return TType.I16; + case Types.I32: + return TType.I32; + case Types.I64: + return TType.I64; + case Types.DOUBLE: + return TType.Double; + case Types.BINARY: + return TType.String; + case Types.LIST: + return TType.List; + case Types.SET: + return TType.Set; + case Types.MAP: + return TType.Map; + case Types.STRUCT: + return TType.Struct; + default: + throw new TProtocolException("don't know what type: " + (byte)(type & 0x0f)); + } + } + + /// <summary> + /// Given a TType value, find the appropriate TCompactProtocol.Types constant. + /// </summary> + private byte getCompactType(TType ttype) + { + return ttypeToCompactType[(int)ttype]; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TField.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TField.cs new file mode 100644 index 000000000..81795577e --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TField.cs @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TField + { + private string name; + private TType type; + private short id; + + public TField(string name, TType type, short id) + :this() + { + this.name = name; + this.type = type; + this.id = id; + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public TType Type + { + get { return type; } + set { type = value; } + } + + public short ID + { + get { return id; } + set { id = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TJSONProtocol.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TJSONProtocol.cs new file mode 100644 index 000000000..9dbdea9aa --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TJSONProtocol.cs @@ -0,0 +1,1124 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; + +using Thrift.Transport; +using System.Globalization; + +namespace Thrift.Protocol +{ + /// <summary> + /// JSON protocol implementation for thrift. + /// <para/> + /// This is a full-featured protocol supporting Write and Read. + /// <para/> + /// Please see the C++ class header for a detailed description of the + /// protocol's wire format. + /// <para/> + /// Adapted from the Java version. + /// </summary> + public class TJSONProtocol : TProtocol + { + /// <summary> + /// Factory for JSON protocol objects. + /// </summary> + public class Factory : TProtocolFactory + { + public TProtocol GetProtocol(TTransport trans) + { + return new TJSONProtocol(trans); + } + } + + private static byte[] COMMA = new byte[] { (byte)',' }; + private static byte[] COLON = new byte[] { (byte)':' }; + private static byte[] LBRACE = new byte[] { (byte)'{' }; + private static byte[] RBRACE = new byte[] { (byte)'}' }; + private static byte[] LBRACKET = new byte[] { (byte)'[' }; + private static byte[] RBRACKET = new byte[] { (byte)']' }; + private static byte[] QUOTE = new byte[] { (byte)'"' }; + private static byte[] BACKSLASH = new byte[] { (byte)'\\' }; + + private byte[] ESCSEQ = new byte[] { (byte)'\\', (byte)'u', (byte)'0', (byte)'0' }; + + private const long VERSION = 1; + private byte[] JSON_CHAR_TABLE = { + 0, 0, 0, 0, 0, 0, 0, 0,(byte)'b',(byte)'t',(byte)'n', 0,(byte)'f',(byte)'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1,(byte)'"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }; + + private char[] ESCAPE_CHARS = "\"\\/bfnrt".ToCharArray(); + + private byte[] ESCAPE_CHAR_VALS = { + (byte)'"', (byte)'\\', (byte)'/', (byte)'\b', (byte)'\f', (byte)'\n', (byte)'\r', (byte)'\t', + }; + + private const int DEF_STRING_SIZE = 16; + + private static byte[] NAME_BOOL = new byte[] { (byte)'t', (byte)'f' }; + private static byte[] NAME_BYTE = new byte[] { (byte)'i', (byte)'8' }; + private static byte[] NAME_I16 = new byte[] { (byte)'i', (byte)'1', (byte)'6' }; + private static byte[] NAME_I32 = new byte[] { (byte)'i', (byte)'3', (byte)'2' }; + private static byte[] NAME_I64 = new byte[] { (byte)'i', (byte)'6', (byte)'4' }; + private static byte[] NAME_DOUBLE = new byte[] { (byte)'d', (byte)'b', (byte)'l' }; + private static byte[] NAME_STRUCT = new byte[] { (byte)'r', (byte)'e', (byte)'c' }; + private static byte[] NAME_STRING = new byte[] { (byte)'s', (byte)'t', (byte)'r' }; + private static byte[] NAME_MAP = new byte[] { (byte)'m', (byte)'a', (byte)'p' }; + private static byte[] NAME_LIST = new byte[] { (byte)'l', (byte)'s', (byte)'t' }; + private static byte[] NAME_SET = new byte[] { (byte)'s', (byte)'e', (byte)'t' }; + + private static byte[] GetTypeNameForTypeID(TType typeID) + { + switch (typeID) + { + case TType.Bool: + return NAME_BOOL; + case TType.Byte: + return NAME_BYTE; + case TType.I16: + return NAME_I16; + case TType.I32: + return NAME_I32; + case TType.I64: + return NAME_I64; + case TType.Double: + return NAME_DOUBLE; + case TType.String: + return NAME_STRING; + case TType.Struct: + return NAME_STRUCT; + case TType.Map: + return NAME_MAP; + case TType.Set: + return NAME_SET; + case TType.List: + return NAME_LIST; + default: + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "Unrecognized type"); + } + } + + private static TType GetTypeIDForTypeName(byte[] name) + { + TType result = TType.Stop; + if (name.Length > 1) + { + switch (name[0]) + { + case (byte)'d': + result = TType.Double; + break; + case (byte)'i': + switch (name[1]) + { + case (byte)'8': + result = TType.Byte; + break; + case (byte)'1': + result = TType.I16; + break; + case (byte)'3': + result = TType.I32; + break; + case (byte)'6': + result = TType.I64; + break; + } + break; + case (byte)'l': + result = TType.List; + break; + case (byte)'m': + result = TType.Map; + break; + case (byte)'r': + result = TType.Struct; + break; + case (byte)'s': + if (name[1] == (byte)'t') + { + result = TType.String; + } + else if (name[1] == (byte)'e') + { + result = TType.Set; + } + break; + case (byte)'t': + result = TType.Bool; + break; + } + } + if (result == TType.Stop) + { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "Unrecognized type"); + } + return result; + } + + /// <summary> + /// Base class for tracking JSON contexts that may require + /// inserting/Reading additional JSON syntax characters + /// This base context does nothing. + /// </summary> + protected class JSONBaseContext + { + protected TJSONProtocol proto; + + public JSONBaseContext(TJSONProtocol proto) + { + this.proto = proto; + } + + public virtual void Write() { } + + public virtual void Read() { } + + public virtual bool EscapeNumbers() { return false; } + } + + /// <summary> + /// Context for JSON lists. Will insert/Read commas before each item except + /// for the first one + /// </summary> + protected class JSONListContext : JSONBaseContext + { + public JSONListContext(TJSONProtocol protocol) + : base(protocol) + { + + } + + private bool first = true; + + public override void Write() + { + if (first) + { + first = false; + } + else + { + proto.trans.Write(COMMA); + } + } + + public override void Read() + { + if (first) + { + first = false; + } + else + { + proto.ReadJSONSyntaxChar(COMMA); + } + } + } + + /// <summary> + /// Context for JSON records. Will insert/Read colons before the value portion + /// of each record pair, and commas before each key except the first. In + /// addition, will indicate that numbers in the key position need to be + /// escaped in quotes (since JSON keys must be strings). + /// </summary> + protected class JSONPairContext : JSONBaseContext + { + public JSONPairContext(TJSONProtocol proto) + : base(proto) + { + + } + + private bool first = true; + private bool colon = true; + + public override void Write() + { + if (first) + { + first = false; + colon = true; + } + else + { + proto.trans.Write(colon ? COLON : COMMA); + colon = !colon; + } + } + + public override void Read() + { + if (first) + { + first = false; + colon = true; + } + else + { + proto.ReadJSONSyntaxChar(colon ? COLON : COMMA); + colon = !colon; + } + } + + public override bool EscapeNumbers() + { + return colon; + } + } + + /// <summary> + /// Holds up to one byte from the transport + /// </summary> + protected class LookaheadReader + { + protected TJSONProtocol proto; + + public LookaheadReader(TJSONProtocol proto) + { + this.proto = proto; + } + + private bool hasData; + private byte[] data = new byte[1]; + + /// <summary> + /// Return and consume the next byte to be Read, either taking it from the + /// data buffer if present or getting it from the transport otherwise. + /// </summary> + public byte Read() + { + if (hasData) + { + hasData = false; + } + else + { + proto.trans.ReadAll(data, 0, 1); + } + return data[0]; + } + + /// <summary> + /// Return the next byte to be Read without consuming, filling the data + /// buffer if it has not been filled alReady. + /// </summary> + public byte Peek() + { + if (!hasData) + { + proto.trans.ReadAll(data, 0, 1); + } + hasData = true; + return data[0]; + } + } + + // Default encoding + protected Encoding utf8Encoding = UTF8Encoding.UTF8; + + // Stack of nested contexts that we may be in + protected Stack<JSONBaseContext> contextStack = new Stack<JSONBaseContext>(); + + // Current context that we are in + protected JSONBaseContext context; + + // Reader that manages a 1-byte buffer + protected LookaheadReader reader; + + /// <summary> + /// Push a new JSON context onto the stack. + /// </summary> + protected void PushContext(JSONBaseContext c) + { + contextStack.Push(context); + context = c; + } + + /// <summary> + /// Pop the last JSON context off the stack + /// </summary> + protected void PopContext() + { + context = contextStack.Pop(); + } + + /// <summary> + /// TJSONProtocol Constructor + /// </summary> + public TJSONProtocol(TTransport trans) + : base(trans) + { + context = new JSONBaseContext(this); + reader = new LookaheadReader(this); + } + + // Temporary buffer used by several methods + private byte[] tempBuffer = new byte[4]; + + /// <summary> + /// Read a byte that must match b[0]; otherwise an exception is thrown. + /// Marked protected to avoid synthetic accessor in JSONListContext.Read + /// and JSONPairContext.Read + /// </summary> + protected void ReadJSONSyntaxChar(byte[] b) + { + byte ch = reader.Read(); + if (ch != b[0]) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Unexpected character:" + (char)ch); + } + } + + /// <summary> + /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its + /// corresponding hex value + /// </summary> + private static byte HexVal(byte ch) + { + if ((ch >= '0') && (ch <= '9')) + { + return (byte)((char)ch - '0'); + } + else if ((ch >= 'a') && (ch <= 'f')) + { + ch += 10; + return (byte)((char)ch - 'a'); + } + else + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected hex character"); + } + } + + /// <summary> + /// Convert a byte containing a hex value to its corresponding hex character + /// </summary> + private static byte HexChar(byte val) + { + val &= 0x0F; + if (val < 10) + { + return (byte)((char)val + '0'); + } + else + { + val -= 10; + return (byte)((char)val + 'a'); + } + } + + /// <summary> + /// Write the bytes in array buf as a JSON characters, escaping as needed + /// </summary> + private void WriteJSONString(byte[] b) + { + context.Write(); + trans.Write(QUOTE); + int len = b.Length; + for (int i = 0; i < len; i++) + { + if ((b[i] & 0x00FF) >= 0x30) + { + if (b[i] == BACKSLASH[0]) + { + trans.Write(BACKSLASH); + trans.Write(BACKSLASH); + } + else + { + trans.Write(b, i, 1); + } + } + else + { + tempBuffer[0] = JSON_CHAR_TABLE[b[i]]; + if (tempBuffer[0] == 1) + { + trans.Write(b, i, 1); + } + else if (tempBuffer[0] > 1) + { + trans.Write(BACKSLASH); + trans.Write(tempBuffer, 0, 1); + } + else + { + trans.Write(ESCSEQ); + tempBuffer[0] = HexChar((byte)(b[i] >> 4)); + tempBuffer[1] = HexChar(b[i]); + trans.Write(tempBuffer, 0, 2); + } + } + } + trans.Write(QUOTE); + } + + /// <summary> + /// Write out number as a JSON value. If the context dictates so, it will be + /// wrapped in quotes to output as a JSON string. + /// </summary> + private void WriteJSONInteger(long num) + { + context.Write(); + string str = num.ToString(); + + bool escapeNum = context.EscapeNumbers(); + if (escapeNum) + trans.Write(QUOTE); + + trans.Write(utf8Encoding.GetBytes(str)); + + if (escapeNum) + trans.Write(QUOTE); + } + + /// <summary> + /// Write out a double as a JSON value. If it is NaN or infinity or if the + /// context dictates escaping, Write out as JSON string. + /// </summary> + private void WriteJSONDouble(double num) + { + context.Write(); + string str = num.ToString("G17", CultureInfo.InvariantCulture); + bool special = false; + + switch (str[0]) + { + case 'N': // NaN + case 'I': // Infinity + special = true; + break; + case '-': + if (str[1] == 'I') + { // -Infinity + special = true; + } + break; + } + + bool escapeNum = special || context.EscapeNumbers(); + + if (escapeNum) + trans.Write(QUOTE); + + trans.Write(utf8Encoding.GetBytes(str)); + + if (escapeNum) + trans.Write(QUOTE); + } + /// <summary> + /// Write out contents of byte array b as a JSON string with base-64 encoded + /// data + /// </summary> + private void WriteJSONBase64(byte[] b) + { + context.Write(); + trans.Write(QUOTE); + + int len = b.Length; + int off = 0; + + while (len >= 3) + { + // Encode 3 bytes at a time + TBase64Utils.encode(b, off, 3, tempBuffer, 0); + trans.Write(tempBuffer, 0, 4); + off += 3; + len -= 3; + } + if (len > 0) + { + // Encode remainder + TBase64Utils.encode(b, off, len, tempBuffer, 0); + trans.Write(tempBuffer, 0, len + 1); + } + + trans.Write(QUOTE); + } + + private void WriteJSONObjectStart() + { + context.Write(); + trans.Write(LBRACE); + PushContext(new JSONPairContext(this)); + } + + private void WriteJSONObjectEnd() + { + PopContext(); + trans.Write(RBRACE); + } + + private void WriteJSONArrayStart() + { + context.Write(); + trans.Write(LBRACKET); + PushContext(new JSONListContext(this)); + } + + private void WriteJSONArrayEnd() + { + PopContext(); + trans.Write(RBRACKET); + } + + public override void WriteMessageBegin(TMessage message) + { + WriteJSONArrayStart(); + WriteJSONInteger(VERSION); + + byte[] b = utf8Encoding.GetBytes(message.Name); + WriteJSONString(b); + + WriteJSONInteger((long)message.Type); + WriteJSONInteger(message.SeqID); + } + + public override void WriteMessageEnd() + { + WriteJSONArrayEnd(); + } + + public override void WriteStructBegin(TStruct str) + { + WriteJSONObjectStart(); + } + + public override void WriteStructEnd() + { + WriteJSONObjectEnd(); + } + + public override void WriteFieldBegin(TField field) + { + WriteJSONInteger(field.ID); + WriteJSONObjectStart(); + WriteJSONString(GetTypeNameForTypeID(field.Type)); + } + + public override void WriteFieldEnd() + { + WriteJSONObjectEnd(); + } + + public override void WriteFieldStop() { } + + public override void WriteMapBegin(TMap map) + { + WriteJSONArrayStart(); + WriteJSONString(GetTypeNameForTypeID(map.KeyType)); + WriteJSONString(GetTypeNameForTypeID(map.ValueType)); + WriteJSONInteger(map.Count); + WriteJSONObjectStart(); + } + + public override void WriteMapEnd() + { + WriteJSONObjectEnd(); + WriteJSONArrayEnd(); + } + + public override void WriteListBegin(TList list) + { + WriteJSONArrayStart(); + WriteJSONString(GetTypeNameForTypeID(list.ElementType)); + WriteJSONInteger(list.Count); + } + + public override void WriteListEnd() + { + WriteJSONArrayEnd(); + } + + public override void WriteSetBegin(TSet set) + { + WriteJSONArrayStart(); + WriteJSONString(GetTypeNameForTypeID(set.ElementType)); + WriteJSONInteger(set.Count); + } + + public override void WriteSetEnd() + { + WriteJSONArrayEnd(); + } + + public override void WriteBool(bool b) + { + WriteJSONInteger(b ? (long)1 : (long)0); + } + + public override void WriteByte(sbyte b) + { + WriteJSONInteger((long)b); + } + + public override void WriteI16(short i16) + { + WriteJSONInteger((long)i16); + } + + public override void WriteI32(int i32) + { + WriteJSONInteger((long)i32); + } + + public override void WriteI64(long i64) + { + WriteJSONInteger(i64); + } + + public override void WriteDouble(double dub) + { + WriteJSONDouble(dub); + } + + public override void WriteString(string str) + { + byte[] b = utf8Encoding.GetBytes(str); + WriteJSONString(b); + } + + public override void WriteBinary(byte[] bin) + { + WriteJSONBase64(bin); + } + + /** + * Reading methods. + */ + + /// <summary> + /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the + /// context if skipContext is true. + /// </summary> + private byte[] ReadJSONString(bool skipContext) + { + MemoryStream buffer = new MemoryStream(); + List<char> codeunits = new List<char>(); + + + if (!skipContext) + { + context.Read(); + } + ReadJSONSyntaxChar(QUOTE); + while (true) + { + byte ch = reader.Read(); + if (ch == QUOTE[0]) + { + break; + } + + // escaped? + if (ch != ESCSEQ[0]) + { + buffer.Write(new byte[] { (byte)ch }, 0, 1); + continue; + } + + // distinguish between \uXXXX and \? + ch = reader.Read(); + if (ch != ESCSEQ[1]) // control chars like \n + { + int off = Array.IndexOf(ESCAPE_CHARS, (char)ch); + if (off == -1) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected control char"); + } + ch = ESCAPE_CHAR_VALS[off]; + buffer.Write(new byte[] { (byte)ch }, 0, 1); + continue; + } + + + // it's \uXXXX + trans.ReadAll(tempBuffer, 0, 4); + var wch = (short)((HexVal((byte)tempBuffer[0]) << 12) + + (HexVal((byte)tempBuffer[1]) << 8) + + (HexVal((byte)tempBuffer[2]) << 4) + + HexVal(tempBuffer[3])); + if (Char.IsHighSurrogate((char)wch)) + { + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected low surrogate char"); + } + codeunits.Add((char)wch); + } + else if (Char.IsLowSurrogate((char)wch)) + { + if (codeunits.Count == 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected high surrogate char"); + } + codeunits.Add((char)wch); + var tmp = utf8Encoding.GetBytes(codeunits.ToArray()); + buffer.Write(tmp, 0, tmp.Length); + codeunits.Clear(); + } + else + { + var tmp = utf8Encoding.GetBytes(new char[] { (char)wch }); + buffer.Write(tmp, 0, tmp.Length); + } + } + + + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected low surrogate char"); + } + + return buffer.ToArray(); + } + + /// <summary> + /// Return true if the given byte could be a valid part of a JSON number. + /// </summary> + private bool IsJSONNumeric(byte b) + { + switch (b) + { + case (byte)'+': + case (byte)'-': + case (byte)'.': + case (byte)'0': + case (byte)'1': + case (byte)'2': + case (byte)'3': + case (byte)'4': + case (byte)'5': + case (byte)'6': + case (byte)'7': + case (byte)'8': + case (byte)'9': + case (byte)'E': + case (byte)'e': + return true; + } + return false; + } + + /// <summary> + /// Read in a sequence of characters that are all valid in JSON numbers. Does + /// not do a complete regex check to validate that this is actually a number. + /// </summary> + private string ReadJSONNumericChars() + { + StringBuilder strbld = new StringBuilder(); + while (true) + { + byte ch = reader.Peek(); + if (!IsJSONNumeric(ch)) + { + break; + } + strbld.Append((char)reader.Read()); + } + return strbld.ToString(); + } + + /// <summary> + /// Read in a JSON number. If the context dictates, Read in enclosing quotes. + /// </summary> + private long ReadJSONInteger() + { + context.Read(); + if (context.EscapeNumbers()) + { + ReadJSONSyntaxChar(QUOTE); + } + + string str = ReadJSONNumericChars(); + if (context.EscapeNumbers()) + { + ReadJSONSyntaxChar(QUOTE); + } + + try + { + return Int64.Parse(str); + } + catch (FormatException fex) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data", fex); + } + } + + /// <summary> + /// Read in a JSON double value. Throw if the value is not wrapped in quotes + /// when expected or if wrapped in quotes when not expected. + /// </summary> + private double ReadJSONDouble() + { + context.Read(); + if (reader.Peek() == QUOTE[0]) + { + byte[] arr = ReadJSONString(true); + double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); + + if (!context.EscapeNumbers() && !Double.IsNaN(dub) && !Double.IsInfinity(dub)) + { + // Throw exception -- we should not be in a string in this case + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Numeric data unexpectedly quoted"); + } + return dub; + } + else + { + if (context.EscapeNumbers()) + { + // This will throw - we should have had a quote if escapeNum == true + ReadJSONSyntaxChar(QUOTE); + } + try + { + return Double.Parse(ReadJSONNumericChars(), CultureInfo.InvariantCulture); + } + catch (FormatException fex) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data", fex); + } + } + } + + /// <summary> + /// Read in a JSON string containing base-64 encoded data and decode it. + /// </summary> + private byte[] ReadJSONBase64() + { + byte[] b = ReadJSONString(false); + int len = b.Length; + int off = 0; + int size = 0; + // reduce len to ignore fill bytes + while ((len > 0) && (b[len - 1] == '=')) + { + --len; + } + // read & decode full byte triplets = 4 source bytes + while (len > 4) + { + // Decode 4 bytes at a time + TBase64Utils.decode(b, off, 4, b, size); // NB: decoded in place + off += 4; + len -= 4; + size += 3; + } + // Don't decode if we hit the end or got a single leftover byte (invalid + // base64 but legal for skip of regular string type) + if (len > 1) + { + // Decode remainder + TBase64Utils.decode(b, off, len, b, size); // NB: decoded in place + size += len - 1; + } + // Sadly we must copy the byte[] (any way around this?) + byte[] result = new byte[size]; + Array.Copy(b, 0, result, 0, size); + return result; + } + + private void ReadJSONObjectStart() + { + context.Read(); + ReadJSONSyntaxChar(LBRACE); + PushContext(new JSONPairContext(this)); + } + + private void ReadJSONObjectEnd() + { + ReadJSONSyntaxChar(RBRACE); + PopContext(); + } + + private void ReadJSONArrayStart() + { + context.Read(); + ReadJSONSyntaxChar(LBRACKET); + PushContext(new JSONListContext(this)); + } + + private void ReadJSONArrayEnd() + { + ReadJSONSyntaxChar(RBRACKET); + PopContext(); + } + + public override TMessage ReadMessageBegin() + { + TMessage message = new TMessage(); + ReadJSONArrayStart(); + if (ReadJSONInteger() != VERSION) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + "Message contained bad version."); + } + + var buf = ReadJSONString(false); + message.Name = utf8Encoding.GetString(buf, 0, buf.Length); + message.Type = (TMessageType)ReadJSONInteger(); + message.SeqID = (int)ReadJSONInteger(); + return message; + } + + public override void ReadMessageEnd() + { + ReadJSONArrayEnd(); + } + + public override TStruct ReadStructBegin() + { + ReadJSONObjectStart(); + return new TStruct(); + } + + public override void ReadStructEnd() + { + ReadJSONObjectEnd(); + } + + public override TField ReadFieldBegin() + { + TField field = new TField(); + byte ch = reader.Peek(); + if (ch == RBRACE[0]) + { + field.Type = TType.Stop; + } + else + { + field.ID = (short)ReadJSONInteger(); + ReadJSONObjectStart(); + field.Type = GetTypeIDForTypeName(ReadJSONString(false)); + } + return field; + } + + public override void ReadFieldEnd() + { + ReadJSONObjectEnd(); + } + + public override TMap ReadMapBegin() + { + TMap map = new TMap(); + ReadJSONArrayStart(); + map.KeyType = GetTypeIDForTypeName(ReadJSONString(false)); + map.ValueType = GetTypeIDForTypeName(ReadJSONString(false)); + map.Count = (int)ReadJSONInteger(); + ReadJSONObjectStart(); + return map; + } + + public override void ReadMapEnd() + { + ReadJSONObjectEnd(); + ReadJSONArrayEnd(); + } + + public override TList ReadListBegin() + { + TList list = new TList(); + ReadJSONArrayStart(); + list.ElementType = GetTypeIDForTypeName(ReadJSONString(false)); + list.Count = (int)ReadJSONInteger(); + return list; + } + + public override void ReadListEnd() + { + ReadJSONArrayEnd(); + } + + public override TSet ReadSetBegin() + { + TSet set = new TSet(); + ReadJSONArrayStart(); + set.ElementType = GetTypeIDForTypeName(ReadJSONString(false)); + set.Count = (int)ReadJSONInteger(); + return set; + } + + public override void ReadSetEnd() + { + ReadJSONArrayEnd(); + } + + public override bool ReadBool() + { + return (ReadJSONInteger() == 0 ? false : true); + } + + public override sbyte ReadByte() + { + return (sbyte)ReadJSONInteger(); + } + + public override short ReadI16() + { + return (short)ReadJSONInteger(); + } + + public override int ReadI32() + { + return (int)ReadJSONInteger(); + } + + public override long ReadI64() + { + return (long)ReadJSONInteger(); + } + + public override double ReadDouble() + { + return ReadJSONDouble(); + } + + public override string ReadString() + { + var buf = ReadJSONString(false); + return utf8Encoding.GetString(buf, 0, buf.Length); + } + + public override byte[] ReadBinary() + { + return ReadJSONBase64(); + } + + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TList.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TList.cs new file mode 100644 index 000000000..0c8f2144a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TList.cs @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TList + { + private TType elementType; + private int count; + + public TList(TType elementType, int count) + :this() + { + this.elementType = elementType; + this.count = count; + } + + public TType ElementType + { + get { return elementType; } + set { elementType = value; } + } + + public int Count + { + get { return count; } + set { count = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMap.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMap.cs new file mode 100644 index 000000000..aba9d3a95 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMap.cs @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TMap + { + private TType keyType; + private TType valueType; + private int count; + + public TMap(TType keyType, TType valueType, int count) + :this() + { + this.keyType = keyType; + this.valueType = valueType; + this.count = count; + } + + public TType KeyType + { + get { return keyType; } + set { keyType = value; } + } + + public TType ValueType + { + get { return valueType; } + set { valueType = value; } + } + + public int Count + { + get { return count; } + set { count = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessage.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessage.cs new file mode 100644 index 000000000..348263c37 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessage.cs @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TMessage + { + private string name; + private TMessageType type; + private int seqID; + + public TMessage(string name, TMessageType type, int seqid) + :this() + { + this.name = name; + this.type = type; + this.seqID = seqid; + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public TMessageType Type + { + get { return type; } + set { type = value; } + } + + public int SeqID + { + get { return seqID; } + set { seqID = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessageType.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessageType.cs new file mode 100644 index 000000000..c7091fede --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMessageType.cs @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; + +namespace Thrift.Protocol +{ + public enum TMessageType + { + Call = 1, + Reply = 2, + Exception = 3, + Oneway = 4 + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProcessor.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProcessor.cs new file mode 100644 index 000000000..aa91c527f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProcessor.cs @@ -0,0 +1,183 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; +using System.Collections.Generic; +using System.IO; + +namespace Thrift.Protocol +{ + /// <summary> + /// <see cref="TMultiplexedProcessor"/> is a <see cref="TProcessor"/> allowing a single <see cref="Thrift.Server.TServer"/> + /// to provide multiple services. + /// <para/> + /// To do so, you instantiate the processor and then register additional processors with it, + /// as shown in the following example: + /// <para/> + /// <code> + /// TMultiplexedProcessor processor = new TMultiplexedProcessor(); + /// + /// processor.registerProcessor( + /// "Calculator", + /// new Calculator.Processor(new CalculatorHandler())); + /// + /// processor.registerProcessor( + /// "WeatherReport", + /// new WeatherReport.Processor(new WeatherReportHandler())); + /// + /// TServerTransport t = new TServerSocket(9090); + /// TSimpleServer server = new TSimpleServer(processor, t); + /// + /// server.serve(); + /// </code> + /// </summary> + public class TMultiplexedProcessor : TProcessor + { + private Dictionary<string, TProcessor> ServiceProcessorMap = new Dictionary<string, TProcessor>(); + + /// <summary> + /// 'Register' a service with this TMultiplexedProcessor. This allows us to broker + /// requests to individual services by using the service name to select them at request time. + /// + /// Args: + /// - serviceName Name of a service, has to be identical to the name + /// declared in the Thrift IDL, e.g. "WeatherReport". + /// - processor Implementation of a service, usually referred to as "handlers", + /// e.g. WeatherReportHandler implementing WeatherReport.Iface. + /// </summary> + public void RegisterProcessor(string serviceName, TProcessor processor) + { + ServiceProcessorMap.Add(serviceName, processor); + } + + + private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt) + { + TApplicationException appex = new TApplicationException(extype, etxt); + + TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); + + oprot.WriteMessageBegin(newMessage); + appex.Write(oprot); + oprot.WriteMessageEnd(); + oprot.Transport.Flush(); + } + + + /// <summary> + /// This implementation of process performs the following steps: + /// + /// - Read the beginning of the message. + /// - Extract the service name from the message. + /// - Using the service name to locate the appropriate processor. + /// - Dispatch to the processor, with a decorated instance of TProtocol + /// that allows readMessageBegin() to return the original TMessage. + /// <para/> + /// Throws an exception if + /// - the message type is not CALL or ONEWAY, + /// - the service name was not found in the message, or + /// - the service name has not been RegisterProcessor()ed. + /// </summary> + public bool Process(TProtocol iprot, TProtocol oprot) + { + /* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the + message header. This pulls the message "off the wire", which we'll + deal with at the end of this method. */ + + try + { + TMessage message = iprot.ReadMessageBegin(); + + if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) + { + Fail(oprot, message, + TApplicationException.ExceptionType.InvalidMessageType, + "Message type CALL or ONEWAY expected"); + return false; + } + + // Extract the service name + int index = message.Name.IndexOf(TMultiplexedProtocol.SEPARATOR); + if (index < 0) + { + Fail(oprot, message, + TApplicationException.ExceptionType.InvalidProtocol, + "Service name not found in message name: " + message.Name + ". " + + "Did you forget to use a TMultiplexProtocol in your client?"); + return false; + } + + // Create a new TMessage, something that can be consumed by any TProtocol + string serviceName = message.Name.Substring(0, index); + TProcessor actualProcessor; + if (!ServiceProcessorMap.TryGetValue(serviceName, out actualProcessor)) + { + Fail(oprot, message, + TApplicationException.ExceptionType.InternalError, + "Service name not found: " + serviceName + ". " + + "Did you forget to call RegisterProcessor()?"); + return false; + } + + // Create a new TMessage, removing the service name + TMessage newMessage = new TMessage( + message.Name.Substring(serviceName.Length + TMultiplexedProtocol.SEPARATOR.Length), + message.Type, + message.SeqID); + + // Dispatch processing to the stored processor + return actualProcessor.Process(new StoredMessageProtocol(iprot, newMessage), oprot); + + } + catch (IOException) + { + return false; // similar to all other processors + } + + } + + /// <summary> + /// Our goal was to work with any protocol. In order to do that, we needed + /// to allow them to call readMessageBegin() and get a TMessage in exactly + /// the standard format, without the service name prepended to TMessage.name. + /// </summary> + private class StoredMessageProtocol : TProtocolDecorator + { + TMessage MsgBegin; + + public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) + : base(protocol) + { + this.MsgBegin = messageBegin; + } + + public override TMessage ReadMessageBegin() + { + return MsgBegin; + } + } + + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProtocol.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProtocol.cs new file mode 100644 index 000000000..1bd420fcc --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TMultiplexedProtocol.cs @@ -0,0 +1,103 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; +using System.Collections.Generic; + +namespace Thrift.Protocol +{ + + /// <summary> + /// TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift + /// client to communicate with a multiplexing Thrift server, by prepending the service name + /// to the function name during function calls. + /// <para/> + /// NOTE: THIS IS NOT TO BE USED BY SERVERS. + /// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. + /// <para/> + /// This example uses a single socket transport to invoke two services: + /// <code> + /// TSocket transport = new TSocket("localhost", 9090); + /// transport.open(); + /// + /// TBinaryProtocol protocol = new TBinaryProtocol(transport); + /// + /// TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); + /// Calculator.Client service = new Calculator.Client(mp); + /// + /// TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); + /// WeatherReport.Client service2 = new WeatherReport.Client(mp2); + /// + /// System.out.println(service.add(2,2)); + /// System.out.println(service2.getTemperature()); + /// </code> + /// </summary> + public class TMultiplexedProtocol : TProtocolDecorator + { + + /// <summary> + /// Used to delimit the service name from the function name. + /// </summary> + public static string SEPARATOR = ":"; + + private string ServiceName; + + /// <summary> + /// Wrap the specified protocol, allowing it to be used to communicate with a + /// multiplexing server. The <paramref name="serviceName"/> is required as it is + /// prepended to the message header so that the multiplexing server can broker + /// the function call to the proper service. + /// </summary> + /// <param name="protocol">Your communication protocol of choice, e.g. <see cref="TBinaryProtocol"/>.</param> + /// <param name="serviceName">The service name of the service communicating via this protocol.</param> + public TMultiplexedProtocol(TProtocol protocol, string serviceName) + : base(protocol) + { + ServiceName = serviceName; + } + + /// <summary> + /// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. + /// </summary> + /// <param name="tMessage">The original message.</param> + public override void WriteMessageBegin(TMessage tMessage) + { + switch (tMessage.Type) + { + case TMessageType.Call: + case TMessageType.Oneway: + base.WriteMessageBegin(new TMessage( + ServiceName + SEPARATOR + tMessage.Name, + tMessage.Type, + tMessage.SeqID)); + break; + + default: + base.WriteMessageBegin(tMessage); + break; + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocol.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocol.cs new file mode 100644 index 000000000..dd7a6e062 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocol.cs @@ -0,0 +1,142 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + public abstract class TProtocol : IDisposable + { + private const int DEFAULT_RECURSION_DEPTH = 64; + + protected TTransport trans; + protected int recursionLimit; + protected int recursionDepth; + + protected TProtocol(TTransport trans) + { + this.trans = trans; + this.recursionLimit = DEFAULT_RECURSION_DEPTH; + this.recursionDepth = 0; + } + + public TTransport Transport + { + get { return trans; } + } + + public int RecursionLimit + { + get { return recursionLimit; } + set { recursionLimit = value; } + } + + public void IncrementRecursionDepth() + { + if (recursionDepth < recursionLimit) + ++recursionDepth; + else + throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); + } + + public void DecrementRecursionDepth() + { + --recursionDepth; + } + + #region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (trans is IDisposable) + (trans as IDisposable).Dispose(); + } + } + _IsDisposed = true; + } + #endregion + + public abstract void WriteMessageBegin(TMessage message); + public abstract void WriteMessageEnd(); + public abstract void WriteStructBegin(TStruct struc); + public abstract void WriteStructEnd(); + public abstract void WriteFieldBegin(TField field); + public abstract void WriteFieldEnd(); + public abstract void WriteFieldStop(); + public abstract void WriteMapBegin(TMap map); + public abstract void WriteMapEnd(); + public abstract void WriteListBegin(TList list); + public abstract void WriteListEnd(); + public abstract void WriteSetBegin(TSet set); + public abstract void WriteSetEnd(); + public abstract void WriteBool(bool b); + public abstract void WriteByte(sbyte b); + public abstract void WriteI16(short i16); + public abstract void WriteI32(int i32); + public abstract void WriteI64(long i64); + public abstract void WriteDouble(double d); + public virtual void WriteString(string s) + { + WriteBinary(Encoding.UTF8.GetBytes(s)); + } + public abstract void WriteBinary(byte[] b); + + public abstract TMessage ReadMessageBegin(); + public abstract void ReadMessageEnd(); + public abstract TStruct ReadStructBegin(); + public abstract void ReadStructEnd(); + public abstract TField ReadFieldBegin(); + public abstract void ReadFieldEnd(); + public abstract TMap ReadMapBegin(); + public abstract void ReadMapEnd(); + public abstract TList ReadListBegin(); + public abstract void ReadListEnd(); + public abstract TSet ReadSetBegin(); + public abstract void ReadSetEnd(); + public abstract bool ReadBool(); + public abstract sbyte ReadByte(); + public abstract short ReadI16(); + public abstract int ReadI32(); + public abstract long ReadI64(); + public abstract double ReadDouble(); + public virtual string ReadString() + { + var buf = ReadBinary(); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + public abstract byte[] ReadBinary(); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolDecorator.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolDecorator.cs new file mode 100644 index 000000000..86000027f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolDecorator.cs @@ -0,0 +1,261 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Text; +using Thrift.Transport; +using System.Collections.Generic; + +namespace Thrift.Protocol +{ + /// <summary> + /// <see cref="TProtocolDecorator"/> forwards all requests to an enclosed <see cref="TProtocol"/> instance, + /// providing a way to author concise concrete decorator subclasses. While it has + /// no abstract methods, it is marked abstract as a reminder that by itself, + /// it does not modify the behaviour of the enclosed <see cref="TProtocol"/>. + /// <para/> + /// See p.175 of Design Patterns (by Gamma et al.) + /// </summary> + /// <seealso cref="TMultiplexedProtocol"/> + public abstract class TProtocolDecorator : TProtocol + { + private TProtocol WrappedProtocol; + + /// <summary> + /// Encloses the specified protocol. + /// </summary> + /// <param name="protocol">All operations will be forward to this protocol. Must be non-null.</param> + public TProtocolDecorator(TProtocol protocol) + : base(protocol.Transport) + { + + WrappedProtocol = protocol; + } + + public override void WriteMessageBegin(TMessage tMessage) + { + WrappedProtocol.WriteMessageBegin(tMessage); + } + + public override void WriteMessageEnd() + { + WrappedProtocol.WriteMessageEnd(); + } + + public override void WriteStructBegin(TStruct tStruct) + { + WrappedProtocol.WriteStructBegin(tStruct); + } + + public override void WriteStructEnd() + { + WrappedProtocol.WriteStructEnd(); + } + + public override void WriteFieldBegin(TField tField) + { + WrappedProtocol.WriteFieldBegin(tField); + } + + public override void WriteFieldEnd() + { + WrappedProtocol.WriteFieldEnd(); + } + + public override void WriteFieldStop() + { + WrappedProtocol.WriteFieldStop(); + } + + public override void WriteMapBegin(TMap tMap) + { + WrappedProtocol.WriteMapBegin(tMap); + } + + public override void WriteMapEnd() + { + WrappedProtocol.WriteMapEnd(); + } + + public override void WriteListBegin(TList tList) + { + WrappedProtocol.WriteListBegin(tList); + } + + public override void WriteListEnd() + { + WrappedProtocol.WriteListEnd(); + } + + public override void WriteSetBegin(TSet tSet) + { + WrappedProtocol.WriteSetBegin(tSet); + } + + public override void WriteSetEnd() + { + WrappedProtocol.WriteSetEnd(); + } + + public override void WriteBool(bool b) + { + WrappedProtocol.WriteBool(b); + } + + public override void WriteByte(sbyte b) + { + WrappedProtocol.WriteByte(b); + } + + public override void WriteI16(short i) + { + WrappedProtocol.WriteI16(i); + } + + public override void WriteI32(int i) + { + WrappedProtocol.WriteI32(i); + } + + public override void WriteI64(long l) + { + WrappedProtocol.WriteI64(l); + } + + public override void WriteDouble(double v) + { + WrappedProtocol.WriteDouble(v); + } + + public override void WriteString(string s) + { + WrappedProtocol.WriteString(s); + } + + public override void WriteBinary(byte[] bytes) + { + WrappedProtocol.WriteBinary(bytes); + } + + public override TMessage ReadMessageBegin() + { + return WrappedProtocol.ReadMessageBegin(); + } + + public override void ReadMessageEnd() + { + WrappedProtocol.ReadMessageEnd(); + } + + public override TStruct ReadStructBegin() + { + return WrappedProtocol.ReadStructBegin(); + } + + public override void ReadStructEnd() + { + WrappedProtocol.ReadStructEnd(); + } + + public override TField ReadFieldBegin() + { + return WrappedProtocol.ReadFieldBegin(); + } + + public override void ReadFieldEnd() + { + WrappedProtocol.ReadFieldEnd(); + } + + public override TMap ReadMapBegin() + { + return WrappedProtocol.ReadMapBegin(); + } + + public override void ReadMapEnd() + { + WrappedProtocol.ReadMapEnd(); + } + + public override TList ReadListBegin() + { + return WrappedProtocol.ReadListBegin(); + } + + public override void ReadListEnd() + { + WrappedProtocol.ReadListEnd(); + } + + public override TSet ReadSetBegin() + { + return WrappedProtocol.ReadSetBegin(); + } + + public override void ReadSetEnd() + { + WrappedProtocol.ReadSetEnd(); + } + + public override bool ReadBool() + { + return WrappedProtocol.ReadBool(); + } + + public override sbyte ReadByte() + { + return WrappedProtocol.ReadByte(); + } + + public override short ReadI16() + { + return WrappedProtocol.ReadI16(); + } + + public override int ReadI32() + { + return WrappedProtocol.ReadI32(); + } + + public override long ReadI64() + { + return WrappedProtocol.ReadI64(); + } + + public override double ReadDouble() + { + return WrappedProtocol.ReadDouble(); + } + + public override string ReadString() + { + return WrappedProtocol.ReadString(); + } + + public override byte[] ReadBinary() + { + return WrappedProtocol.ReadBinary(); + } + } + +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolException.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolException.cs new file mode 100644 index 000000000..7bef23685 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolException.cs @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Protocol +{ + public class TProtocolException : TException + { + public const int UNKNOWN = 0; + public const int INVALID_DATA = 1; + public const int NEGATIVE_SIZE = 2; + public const int SIZE_LIMIT = 3; + public const int BAD_VERSION = 4; + public const int NOT_IMPLEMENTED = 5; + public const int DEPTH_LIMIT = 6; + + protected int type_ = UNKNOWN; + + public TProtocolException() + : base() + { + } + + public TProtocolException(int type, Exception inner = null) + : base(string.Empty, inner) + { + type_ = type; + } + + public TProtocolException(int type, string message, Exception inner = null) + : base(message, inner) + { + type_ = type; + } + + public TProtocolException(string message, Exception inner = null) + : base(message, inner) + { + } + + public int getType() + { + return type_; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolFactory.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolFactory.cs new file mode 100644 index 000000000..71360a19a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolFactory.cs @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + public interface TProtocolFactory + { + TProtocol GetProtocol(TTransport trans); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolUtil.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolUtil.cs new file mode 100644 index 000000000..d995c6ce7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TProtocolUtil.cs @@ -0,0 +1,108 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Protocol +{ + public static class TProtocolUtil + { + public static void Skip(TProtocol prot, TType type) + { + prot.IncrementRecursionDepth(); + try + { + switch (type) + { + case TType.Bool: + prot.ReadBool(); + break; + case TType.Byte: + prot.ReadByte(); + break; + case TType.I16: + prot.ReadI16(); + break; + case TType.I32: + prot.ReadI32(); + break; + case TType.I64: + prot.ReadI64(); + break; + case TType.Double: + prot.ReadDouble(); + break; + case TType.String: + // Don't try to decode the string, just skip it. + prot.ReadBinary(); + break; + case TType.Struct: + prot.ReadStructBegin(); + while (true) + { + TField field = prot.ReadFieldBegin(); + if (field.Type == TType.Stop) + { + break; + } + Skip(prot, field.Type); + prot.ReadFieldEnd(); + } + prot.ReadStructEnd(); + break; + case TType.Map: + TMap map = prot.ReadMapBegin(); + for (int i = 0; i < map.Count; i++) + { + Skip(prot, map.KeyType); + Skip(prot, map.ValueType); + } + prot.ReadMapEnd(); + break; + case TType.Set: + TSet set = prot.ReadSetBegin(); + for (int i = 0; i < set.Count; i++) + { + Skip(prot, set.ElementType); + } + prot.ReadSetEnd(); + break; + case TType.List: + TList list = prot.ReadListBegin(); + for (int i = 0; i < list.Count; i++) + { + Skip(prot, list.ElementType); + } + prot.ReadListEnd(); + break; + default: + throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); + } + } + finally + { + prot.DecrementRecursionDepth(); + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TSet.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TSet.cs new file mode 100644 index 000000000..a918ab537 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TSet.cs @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TSet + { + private TType elementType; + private int count; + + public TSet(TType elementType, int count) + :this() + { + this.elementType = elementType; + this.count = count; + } + + public TSet(TList list) + : this(list.ElementType, list.Count) + { + } + + public TType ElementType + { + get { return elementType; } + set { elementType = value; } + } + + public int Count + { + get { return count; } + set { count = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TStruct.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TStruct.cs new file mode 100644 index 000000000..f4844a4c9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TStruct.cs @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Protocol +{ + public struct TStruct + { + private string name; + + public TStruct(string name) + :this() + { + this.name = name; + } + + public string Name + { + get { return name; } + set { name = value; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Protocol/TType.cs b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TType.cs new file mode 100644 index 000000000..9ce915e08 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Protocol/TType.cs @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Protocol +{ + public enum TType : byte + { + Stop = 0, + Void = 1, + Bool = 2, + Byte = 3, + Double = 4, + I16 = 6, + I32 = 8, + I64 = 10, + String = 11, + Struct = 12, + Map = 13, + Set = 14, + List = 15 + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Server/TServer.cs b/src/jaegertracing/thrift/lib/csharp/src/Server/TServer.cs new file mode 100644 index 000000000..2bc04f3a0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Server/TServer.cs @@ -0,0 +1,155 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using Thrift.Protocol; +using Thrift.Transport; +using System.IO; + +namespace Thrift.Server +{ + public abstract class TServer + { + //Attributes + protected TProcessorFactory processorFactory; + protected TServerTransport serverTransport; + protected TTransportFactory inputTransportFactory; + protected TTransportFactory outputTransportFactory; + protected TProtocolFactory inputProtocolFactory; + protected TProtocolFactory outputProtocolFactory; + protected TServerEventHandler serverEventHandler = null; + + //Methods + public void setEventHandler(TServerEventHandler seh) + { + serverEventHandler = seh; + } + public TServerEventHandler getEventHandler() + { + return serverEventHandler; + } + + //Log delegation + public delegate void LogDelegate(string str); + private LogDelegate _logDelegate; + protected LogDelegate logDelegate + { + get { return _logDelegate; } + set { _logDelegate = (value != null) ? value : DefaultLogDelegate; } + } + protected static void DefaultLogDelegate(string s) + { + Console.Error.WriteLine(s); + } + + //Construction + public TServer(TProcessor processor, + TServerTransport serverTransport) + : this(processor, serverTransport, + new TTransportFactory(), + new TTransportFactory(), + new TBinaryProtocol.Factory(), + new TBinaryProtocol.Factory(), + DefaultLogDelegate) + { + } + + public TServer(TProcessor processor, + TServerTransport serverTransport, + LogDelegate logDelegate) + : this(processor, + serverTransport, + new TTransportFactory(), + new TTransportFactory(), + new TBinaryProtocol.Factory(), + new TBinaryProtocol.Factory(), + logDelegate) + { + } + + public TServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory) + : this(processor, + serverTransport, + transportFactory, + transportFactory, + new TBinaryProtocol.Factory(), + new TBinaryProtocol.Factory(), + DefaultLogDelegate) + { + } + + public TServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : this(processor, + serverTransport, + transportFactory, + transportFactory, + protocolFactory, + protocolFactory, + DefaultLogDelegate) + { + } + + public TServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + LogDelegate logDelegate) + { + this.processorFactory = new TSingletonProcessorFactory(processor); + this.serverTransport = serverTransport; + this.inputTransportFactory = inputTransportFactory; + this.outputTransportFactory = outputTransportFactory; + this.inputProtocolFactory = inputProtocolFactory; + this.outputProtocolFactory = outputProtocolFactory; + this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate; + } + + public TServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + LogDelegate logDelegate) + { + this.processorFactory = processorFactory; + this.serverTransport = serverTransport; + this.inputTransportFactory = inputTransportFactory; + this.outputTransportFactory = outputTransportFactory; + this.inputProtocolFactory = inputProtocolFactory; + this.outputProtocolFactory = outputProtocolFactory; + this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate; + } + + //Abstract Interface + public abstract void Serve(); + public abstract void Stop(); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Server/TServerEventHandler.cs b/src/jaegertracing/thrift/lib/csharp/src/Server/TServerEventHandler.cs new file mode 100644 index 000000000..e81efc6af --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Server/TServerEventHandler.cs @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Server +{ + /// <summary> + /// Interface implemented by server users to handle events from the server. + /// </summary> + public interface TServerEventHandler + { + /// <summary> + /// Called before the server begins. + /// </summary> + void preServe(); + + /// <summary> + /// Called when a new client has connected and is about to being processing. + /// </summary> + object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); + + /// <summary> + /// Called when a client has finished request-handling to delete server context. + /// </summary> + void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); + + /// <summary> + /// Called when a client is about to call the processor. + /// </summary> + void processContext(object serverContext, Thrift.Transport.TTransport transport); + }; +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Server/TSimpleServer.cs b/src/jaegertracing/thrift/lib/csharp/src/Server/TSimpleServer.cs new file mode 100644 index 000000000..4e7ea96f4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Server/TSimpleServer.cs @@ -0,0 +1,180 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using Thrift.Transport; +using Thrift.Protocol; + +namespace Thrift.Server +{ + /// <summary> + /// Simple single-threaded server for testing. + /// </summary> + public class TSimpleServer : TServer + { + private bool stop = false; + + public TSimpleServer(TProcessor processor, + TServerTransport serverTransport) + : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate) + { + } + + public TSimpleServer(TProcessor processor, + TServerTransport serverTransport, + LogDelegate logDel) + : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel) + { + } + + public TSimpleServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory) + : base(processor, + serverTransport, + transportFactory, + transportFactory, + new TBinaryProtocol.Factory(), + new TBinaryProtocol.Factory(), + DefaultLogDelegate) + { + } + + public TSimpleServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : base(processor, + serverTransport, + transportFactory, + transportFactory, + protocolFactory, + protocolFactory, + DefaultLogDelegate) + { + } + + public TSimpleServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : base(processorFactory, + serverTransport, + transportFactory, + transportFactory, + protocolFactory, + protocolFactory, + DefaultLogDelegate) + { + } + + public override void Serve() + { + try + { + serverTransport.Listen(); + } + catch (TTransportException ttx) + { + logDelegate(ttx.ToString()); + return; + } + + //Fire the preServe server event when server is up but before any client connections + if (serverEventHandler != null) + serverEventHandler.preServe(); + + while (!stop) + { + TProcessor processor = null; + TTransport client = null; + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + object connectionContext = null; + try + { + using (client = serverTransport.Accept()) + { + processor = processorFactory.GetProcessor(client); + if (client != null) + { + using (inputTransport = inputTransportFactory.GetTransport(client)) + { + using (outputTransport = outputTransportFactory.GetTransport(client)) + { + inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); + outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); + + //Recover event handler (if any) and fire createContext server event when a client connects + if (serverEventHandler != null) + connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); + + //Process client requests until client disconnects + while (!stop) + { + if (!inputTransport.Peek()) + break; + + //Fire processContext server event + //N.B. This is the pattern implemented in C++ and the event fires provisionally. + //That is to say it may be many minutes between the event firing and the client request + //actually arriving or the client may hang up without ever makeing a request. + if (serverEventHandler != null) + serverEventHandler.processContext(connectionContext, inputTransport); + //Process client request (blocks until transport is readable) + if (!processor.Process(inputProtocol, outputProtocol)) + break; + } + } + } + } + } + } + catch (TTransportException ttx) + { + if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) + { + logDelegate(ttx.ToString()); + } + } + catch (Exception x) + { + //Unexpected + logDelegate(x.ToString()); + } + + //Fire deleteContext server event after client disconnects + if (serverEventHandler != null) + serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); + } + } + + public override void Stop() + { + stop = true; + serverTransport.Close(); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadPoolServer.cs b/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadPoolServer.cs new file mode 100644 index 000000000..a494ce7bd --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadPoolServer.cs @@ -0,0 +1,295 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Threading; +using Thrift.Protocol; +using Thrift.Transport; + +namespace Thrift.Server +{ + /// <summary> + /// Server that uses C# built-in ThreadPool to spawn threads when handling requests. + /// </summary> + public class TThreadPoolServer : TServer + { + private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults + private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults + private volatile bool stop = false; + + public struct Configuration + { + public int MinWorkerThreads; + public int MaxWorkerThreads; + public int MinIOThreads; + public int MaxIOThreads; + + public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS) + { + MinWorkerThreads = min; + MaxWorkerThreads = max; + MinIOThreads = min; + MaxIOThreads = max; + } + + public Configuration(int minWork, int maxWork, int minIO, int maxIO) + { + MinWorkerThreads = minWork; + MaxWorkerThreads = maxWork; + MinIOThreads = minIO; + MaxIOThreads = maxIO; + } + } + + public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + new Configuration(), DefaultLogDelegate) + { + } + + public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + new Configuration(), logDelegate) + { + } + + public TThreadPoolServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : this(new TSingletonProcessorFactory(processor), serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + new Configuration(), DefaultLogDelegate) + { + } + + public TThreadPoolServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : this(processorFactory, serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + new Configuration(), DefaultLogDelegate) + { + } + + public TThreadPoolServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel) + : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, + new Configuration(minThreadPoolThreads, maxThreadPoolThreads), + logDel) + { + } + + public TThreadPoolServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + Configuration threadConfig, + LogDelegate logDel) + : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, logDel) + { + lock (typeof(TThreadPoolServer)) + { + if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0)) + { + int work, comm; + ThreadPool.GetMaxThreads(out work, out comm); + if (threadConfig.MaxWorkerThreads > 0) + work = threadConfig.MaxWorkerThreads; + if (threadConfig.MaxIOThreads > 0) + comm = threadConfig.MaxIOThreads; + if (!ThreadPool.SetMaxThreads(work, comm)) + throw new Exception("Error: could not SetMaxThreads in ThreadPool"); + } + + if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0)) + { + int work, comm; + ThreadPool.GetMinThreads(out work, out comm); + if (threadConfig.MinWorkerThreads > 0) + work = threadConfig.MinWorkerThreads; + if (threadConfig.MinIOThreads > 0) + comm = threadConfig.MinIOThreads; + if (!ThreadPool.SetMinThreads(work, comm)) + throw new Exception("Error: could not SetMinThreads in ThreadPool"); + } + } + } + + + /// <summary> + /// Use new ThreadPool thread for each new client connection. + /// </summary> + public override void Serve() + { + try + { + serverTransport.Listen(); + } + catch (TTransportException ttx) + { + logDelegate("Error, could not listen on ServerTransport: " + ttx); + return; + } + + //Fire the preServe server event when server is up but before any client connections + if (serverEventHandler != null) + serverEventHandler.preServe(); + + while (!stop) + { + int failureCount = 0; + try + { + TTransport client = serverTransport.Accept(); + ThreadPool.QueueUserWorkItem(this.Execute, client); + } + catch (TTransportException ttx) + { + if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) + { + ++failureCount; + logDelegate(ttx.ToString()); + } + + } + } + + if (stop) + { + try + { + serverTransport.Close(); + } + catch (TTransportException ttx) + { + logDelegate("TServerTransport failed on close: " + ttx.Message); + } + stop = false; + } + } + + /// <summary> + /// Loops on processing a client forever + /// threadContext will be a TTransport instance + /// </summary> + /// <param name="threadContext"></param> + private void Execute(object threadContext) + { + using (TTransport client = (TTransport)threadContext) + { + TProcessor processor = processorFactory.GetProcessor(client, this); + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + object connectionContext = null; + try + { + try + { + inputTransport = inputTransportFactory.GetTransport(client); + outputTransport = outputTransportFactory.GetTransport(client); + inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); + outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); + + //Recover event handler (if any) and fire createContext server event when a client connects + if (serverEventHandler != null) + connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); + + //Process client requests until client disconnects + while (!stop) + { + if (!inputTransport.Peek()) + break; + + //Fire processContext server event + //N.B. This is the pattern implemented in C++ and the event fires provisionally. + //That is to say it may be many minutes between the event firing and the client request + //actually arriving or the client may hang up without ever makeing a request. + if (serverEventHandler != null) + serverEventHandler.processContext(connectionContext, inputTransport); + //Process client request (blocks until transport is readable) + if (!processor.Process(inputProtocol, outputProtocol)) + break; + } + } + catch (TTransportException) + { + //Usually a client disconnect, expected + } + catch (Exception x) + { + //Unexpected + logDelegate("Error: " + x); + } + + //Fire deleteContext server event after client disconnects + if (serverEventHandler != null) + serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); + + } + finally + { + //Close transports + if (inputTransport != null) + inputTransport.Close(); + if (outputTransport != null) + outputTransport.Close(); + + // disposable stuff should be disposed + if (inputProtocol != null) + inputProtocol.Dispose(); + if (outputProtocol != null) + outputProtocol.Dispose(); + if (inputTransport != null) + inputTransport.Dispose(); + if (outputTransport != null) + outputTransport.Dispose(); + } + } + } + + public override void Stop() + { + stop = true; + serverTransport.Close(); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadedServer.cs b/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadedServer.cs new file mode 100644 index 000000000..cc051a33b --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Server/TThreadedServer.cs @@ -0,0 +1,282 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.Threading; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Transport; + +namespace Thrift.Server +{ + /// <summary> + /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests. + /// </summary> + public class TThreadedServer : TServer + { + private const int DEFAULT_MAX_THREADS = 100; + private volatile bool stop = false; + private readonly int maxThreads; + + private Queue<TTransport> clientQueue; + private THashSet<Thread> clientThreads; + private object clientLock; + private Thread workerThread; + + public int ClientThreadsCount + { + get { return clientThreads.Count; } + } + + public TThreadedServer(TProcessor processor, TServerTransport serverTransport) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + DEFAULT_MAX_THREADS, DefaultLogDelegate) + { + } + + public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + DEFAULT_MAX_THREADS, logDelegate) + { + } + + + public TThreadedServer(TProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : this(new TSingletonProcessorFactory(processor), serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + DEFAULT_MAX_THREADS, DefaultLogDelegate) + { + } + + public TThreadedServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory transportFactory, + TProtocolFactory protocolFactory) + : this(processorFactory, serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + DEFAULT_MAX_THREADS, DefaultLogDelegate) + { + } + public TThreadedServer(TProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + int maxThreads, LogDelegate logDel) + : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, logDel) + { + this.maxThreads = maxThreads; + clientQueue = new Queue<TTransport>(); + clientLock = new object(); + clientThreads = new THashSet<Thread>(); + } + + /// <summary> + /// Use new Thread for each new client connection. block until numConnections < maxThreads. + /// </summary> + public override void Serve() + { + try + { + //start worker thread + workerThread = new Thread(new ThreadStart(Execute)); + workerThread.Start(); + serverTransport.Listen(); + } + catch (TTransportException ttx) + { + logDelegate("Error, could not listen on ServerTransport: " + ttx); + return; + } + + //Fire the preServe server event when server is up but before any client connections + if (serverEventHandler != null) + serverEventHandler.preServe(); + + while (!stop) + { + int failureCount = 0; + try + { + TTransport client = serverTransport.Accept(); + lock (clientLock) + { + clientQueue.Enqueue(client); + Monitor.Pulse(clientLock); + } + } + catch (TTransportException ttx) + { + if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) + { + ++failureCount; + logDelegate(ttx.ToString()); + } + + } + } + + if (stop) + { + try + { + serverTransport.Close(); + } + catch (TTransportException ttx) + { + logDelegate("TServeTransport failed on close: " + ttx.Message); + } + stop = false; + } + } + + /// <summary> + /// Loops on processing a client forever + /// </summary> + private void Execute() + { + while (!stop) + { + TTransport client; + Thread t; + lock (clientLock) + { + //don't dequeue if too many connections + while (clientThreads.Count >= maxThreads) + { + Monitor.Wait(clientLock); + } + + while (clientQueue.Count == 0) + { + Monitor.Wait(clientLock); + } + + client = clientQueue.Dequeue(); + t = new Thread(new ParameterizedThreadStart(ClientWorker)); + clientThreads.Add(t); + } + //start processing requests from client on new thread + t.Start(client); + } + } + + private void ClientWorker(object context) + { + using (TTransport client = (TTransport)context) + { + TProcessor processor = processorFactory.GetProcessor(client); + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + object connectionContext = null; + try + { + try + { + inputTransport = inputTransportFactory.GetTransport(client); + outputTransport = outputTransportFactory.GetTransport(client); + inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); + outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); + + //Recover event handler (if any) and fire createContext server event when a client connects + if (serverEventHandler != null) + connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); + + //Process client requests until client disconnects + while (!stop) + { + if (!inputTransport.Peek()) + break; + + //Fire processContext server event + //N.B. This is the pattern implemented in C++ and the event fires provisionally. + //That is to say it may be many minutes between the event firing and the client request + //actually arriving or the client may hang up without ever makeing a request. + if (serverEventHandler != null) + serverEventHandler.processContext(connectionContext, inputTransport); + //Process client request (blocks until transport is readable) + if (!processor.Process(inputProtocol, outputProtocol)) + break; + } + } + catch (TTransportException) + { + //Usually a client disconnect, expected + } + catch (Exception x) + { + //Unexpected + logDelegate("Error: " + x); + } + + //Fire deleteContext server event after client disconnects + if (serverEventHandler != null) + serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); + + lock (clientLock) + { + clientThreads.Remove(Thread.CurrentThread); + Monitor.Pulse(clientLock); + } + + } + finally + { + //Close transports + if (inputTransport != null) + inputTransport.Close(); + if (outputTransport != null) + outputTransport.Close(); + + // disposable stuff should be disposed + if (inputProtocol != null) + inputProtocol.Dispose(); + if (outputProtocol != null) + outputProtocol.Dispose(); + } + } + } + + public override void Stop() + { + stop = true; + serverTransport.Close(); + //clean up all the threads myself + workerThread.Abort(); + foreach (Thread t in clientThreads) + { + t.Abort(); + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TApplicationException.cs b/src/jaegertracing/thrift/lib/csharp/src/TApplicationException.cs new file mode 100644 index 000000000..8dd7ae578 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TApplicationException.cs @@ -0,0 +1,146 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using Thrift.Protocol; + +namespace Thrift +{ + public class TApplicationException : TException + { + protected ExceptionType type; + + public TApplicationException() + { + } + + public TApplicationException(ExceptionType type) + { + this.type = type; + } + + public TApplicationException(ExceptionType type, string message) + : base(message, null) // TApplicationException is serializable, but we never serialize InnerException + { + this.type = type; + } + + public static TApplicationException Read(TProtocol iprot) + { + TField field; + + string message = null; + ExceptionType type = ExceptionType.Unknown; + + iprot.ReadStructBegin(); + while (true) + { + field = iprot.ReadFieldBegin(); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case 1: + if (field.Type == TType.String) + { + message = iprot.ReadString(); + } + else + { + TProtocolUtil.Skip(iprot, field.Type); + } + break; + case 2: + if (field.Type == TType.I32) + { + type = (ExceptionType)iprot.ReadI32(); + } + else + { + TProtocolUtil.Skip(iprot, field.Type); + } + break; + default: + TProtocolUtil.Skip(iprot, field.Type); + break; + } + + iprot.ReadFieldEnd(); + } + + iprot.ReadStructEnd(); + + return new TApplicationException(type, message); + } + + public void Write(TProtocol oprot) + { + TStruct struc = new TStruct("TApplicationException"); + TField field = new TField(); + + oprot.WriteStructBegin(struc); + + if (!string.IsNullOrEmpty(Message)) + { + field.Name = "message"; + field.Type = TType.String; + field.ID = 1; + oprot.WriteFieldBegin(field); + oprot.WriteString(Message); + oprot.WriteFieldEnd(); + } + + field.Name = "type"; + field.Type = TType.I32; + field.ID = 2; + oprot.WriteFieldBegin(field); + oprot.WriteI32((int)type); + oprot.WriteFieldEnd(); + oprot.WriteFieldStop(); + oprot.WriteStructEnd(); + } + + public enum ExceptionType + { + Unknown, + UnknownMethod, + InvalidMessageType, + WrongMethodName, + BadSequenceID, + MissingResult, + InternalError, + ProtocolError, + InvalidTransform, + InvalidProtocol, + UnsupportedClientType + } + + public ExceptionType Type + { + get { return type; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TAsyncProcessor.cs b/src/jaegertracing/thrift/lib/csharp/src/TAsyncProcessor.cs new file mode 100644 index 000000000..ab432255b --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TAsyncProcessor.cs @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Threading.Tasks; +using Thrift.Protocol; + +namespace Thrift +{ + /// <summary> + /// Processes a message asynchronously. + /// </summary> + public interface TAsyncProcessor + { + /// <summary> + /// Processes the next part of the message. + /// </summary> + /// <param name="iprot">The input protocol.</param> + /// <param name="oprot">The output protocol.</param> + /// <returns>true if there's more to process, false otherwise.</returns> + Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TControllingHandler.cs b/src/jaegertracing/thrift/lib/csharp/src/TControllingHandler.cs new file mode 100644 index 000000000..7b5203a5f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TControllingHandler.cs @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using Thrift.Server; + +namespace Thrift +{ + public interface TControllingHandler + { + TServer server { get; set; } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TException.cs b/src/jaegertracing/thrift/lib/csharp/src/TException.cs new file mode 100644 index 000000000..b9fae6e9f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TException.cs @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift +{ + public class TException : Exception + { + public TException() + { + } + + public TException(string message, Exception inner = null) + : base(message, inner) + { + } + + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TProcessor.cs b/src/jaegertracing/thrift/lib/csharp/src/TProcessor.cs new file mode 100644 index 000000000..71ce75508 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TProcessor.cs @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using Thrift.Protocol; + +namespace Thrift +{ + public interface TProcessor + { + bool Process(TProtocol iprot, TProtocol oprot); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TProcessorFactory.cs b/src/jaegertracing/thrift/lib/csharp/src/TProcessorFactory.cs new file mode 100644 index 000000000..fdf631bc7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TProcessorFactory.cs @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using Thrift.Server; +using Thrift.Transport; + +namespace Thrift +{ + public interface TProcessorFactory + { + TProcessor GetProcessor(TTransport trans, TServer server = null); + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TPrototypeProcessorFactory.cs b/src/jaegertracing/thrift/lib/csharp/src/TPrototypeProcessorFactory.cs new file mode 100644 index 000000000..0b47261fb --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TPrototypeProcessorFactory.cs @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Thrift.Server; +using Thrift.Transport; + +namespace Thrift +{ + public class TPrototypeProcessorFactory<P, H> : TProcessorFactory where P : TProcessor + { + object[] handlerArgs = null; + + public TPrototypeProcessorFactory() + { + handlerArgs = new object[0]; + } + + public TPrototypeProcessorFactory(params object[] handlerArgs) + { + this.handlerArgs = handlerArgs; + } + + public TProcessor GetProcessor(TTransport trans, TServer server = null) + { + H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs); + + TControllingHandler handlerServerRef = handler as TControllingHandler; + if (handlerServerRef != null) + { + handlerServerRef.server = server; + } + return Activator.CreateInstance(typeof(P), new object[] { handler }) as TProcessor; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/TSingletonProcessorFactory.cs b/src/jaegertracing/thrift/lib/csharp/src/TSingletonProcessorFactory.cs new file mode 100644 index 000000000..ed2897ba3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/TSingletonProcessorFactory.cs @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Thrift.Server; +using Thrift.Transport; + +namespace Thrift +{ + public class TSingletonProcessorFactory : TProcessorFactory + { + private readonly TProcessor processor_; + + public TSingletonProcessorFactory(TProcessor processor) + { + processor_ = processor; + } + + public TProcessor GetProcessor(TTransport trans, TServer server = null) + { + return processor_; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Thrift.45.csproj b/src/jaegertracing/thrift/lib/csharp/src/Thrift.45.csproj new file mode 100644 index 000000000..146e7f8ed --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Thrift.45.csproj @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{EBCE35DA-CF6A-42BC-A357-A9C09B534299}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Thrift</RootNamespace> + <AssemblyName>Thrift45</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>portable</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>TRACE;DEBUG;NET45</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>portable</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE;NET45</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <SignAssembly>true</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <AssemblyOriginatorKeyFile>thrift.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Collections\TCollections.cs" /> + <Compile Include="Collections\THashSet.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Protocol\TAbstractBase.cs" /> + <Compile Include="Protocol\TBase.cs" /> + <Compile Include="Protocol\TBase64Utils.cs" /> + <Compile Include="Protocol\TBinaryProtocol.cs" /> + <Compile Include="Protocol\TCompactProtocol.cs" /> + <Compile Include="Protocol\TField.cs" /> + <Compile Include="Protocol\TJSONProtocol.cs" /> + <Compile Include="Protocol\TList.cs" /> + <Compile Include="Protocol\TMap.cs" /> + <Compile Include="Protocol\TMessage.cs" /> + <Compile Include="Protocol\TMessageType.cs" /> + <Compile Include="Protocol\TMultiplexedProcessor.cs" /> + <Compile Include="Protocol\TMultiplexedProtocol.cs" /> + <Compile Include="Protocol\TProtocol.cs" /> + <Compile Include="Protocol\TProtocolDecorator.cs" /> + <Compile Include="Protocol\TProtocolException.cs" /> + <Compile Include="Protocol\TProtocolFactory.cs" /> + <Compile Include="Protocol\TProtocolUtil.cs" /> + <Compile Include="Protocol\TSet.cs" /> + <Compile Include="Protocol\TStruct.cs" /> + <Compile Include="Protocol\TType.cs" /> + <Compile Include="Server\TServer.cs" /> + <Compile Include="Server\TServerEventHandler.cs" /> + <Compile Include="Server\TSimpleServer.cs" /> + <Compile Include="Server\TThreadedServer.cs" /> + <Compile Include="Server\TThreadPoolServer.cs" /> + <Compile Include="TApplicationException.cs" /> + <Compile Include="TAsyncProcessor.cs" /> + <Compile Include="TControllingHandler.cs" /> + <Compile Include="TException.cs" /> + <Compile Include="TProcessor.cs" /> + <Compile Include="TProcessorFactory.cs" /> + <Compile Include="TPrototypeProcessorFactory.cs" /> + <Compile Include="Transport\TBufferedTransport.cs" /> + <Compile Include="Transport\TFramedTransport.cs" /> + <Compile Include="Transport\THttpClient.cs" /> + <Compile Include="Transport\THttpHandler.cs" /> + <Compile Include="Transport\THttpTaskAsyncHandler.cs" /> + <Compile Include="Transport\TMemoryBuffer.cs" /> + <Compile Include="Transport\TNamedPipeClientTransport.cs" /> + <Compile Include="Transport\TNamedPipeServerTransport.cs" /> + <Compile Include="Transport\TServerSocket.cs" /> + <Compile Include="Transport\TServerTransport.cs" /> + <Compile Include="Transport\TSilverlightSocket.cs" /> + <Compile Include="Transport\TSocket.cs" /> + <Compile Include="Transport\TSocketVersionizer.cs" /> + <Compile Include="Transport\TStreamTransport.cs" /> + <Compile Include="Transport\TTLSServerSocket.cs" /> + <Compile Include="Transport\TTLSSocket.cs" /> + <Compile Include="Transport\TTransport.cs" /> + <Compile Include="Transport\TTransportException.cs" /> + <Compile Include="Transport\TTransportFactory.cs" /> + <Compile Include="TSingletonProcessorFactory.cs" /> + </ItemGroup> + <ItemGroup> + <Folder Include="Server\Collections\" /> + <Folder Include="Server\Protocol\" /> + </ItemGroup> + <ItemGroup> + <None Include="thrift.snk" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/src/Thrift.csproj b/src/jaegertracing/thrift/lib/csharp/src/Thrift.csproj new file mode 100644 index 000000000..da69554d1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Thrift.csproj @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</ProjectGuid> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <OutputType>Library</OutputType> + <NoStandardLibraries>false</NoStandardLibraries> + <AssemblyName>Thrift</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <RootNamespace>Thrift</RootNamespace> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>0.13.0.0</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>portable</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>TRACE;DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>portable</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants> + </DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup> + <SignAssembly>true</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <AssemblyOriginatorKeyFile>thrift.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Web" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Collections\TCollections.cs" /> + <Compile Include="Collections\THashSet.cs" /> + <Compile Include="Net35\ExtensionsNet35.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Protocol\TAbstractBase.cs" /> + <Compile Include="Protocol\TBase.cs" /> + <Compile Include="Protocol\TBase64Utils.cs" /> + <Compile Include="Protocol\TBinaryProtocol.cs" /> + <Compile Include="Protocol\TCompactProtocol.cs" /> + <Compile Include="Protocol\TField.cs" /> + <Compile Include="Protocol\TJSONProtocol.cs" /> + <Compile Include="Protocol\TList.cs" /> + <Compile Include="Protocol\TMap.cs" /> + <Compile Include="Protocol\TMessage.cs" /> + <Compile Include="Protocol\TMessageType.cs" /> + <Compile Include="Protocol\TMultiplexedProcessor.cs" /> + <Compile Include="Protocol\TMultiplexedProtocol.cs" /> + <Compile Include="Protocol\TProtocol.cs" /> + <Compile Include="Protocol\TProtocolDecorator.cs" /> + <Compile Include="Protocol\TProtocolException.cs" /> + <Compile Include="Protocol\TProtocolFactory.cs" /> + <Compile Include="Protocol\TProtocolUtil.cs" /> + <Compile Include="Protocol\TSet.cs" /> + <Compile Include="Protocol\TStruct.cs" /> + <Compile Include="Protocol\TType.cs" /> + <Compile Include="Server\TServer.cs" /> + <Compile Include="Server\TServerEventHandler.cs" /> + <Compile Include="Server\TSimpleServer.cs" /> + <Compile Include="Server\TThreadedServer.cs" /> + <Compile Include="Server\TThreadPoolServer.cs" /> + <Compile Include="TApplicationException.cs" /> + <Compile Include="TControllingHandler.cs" /> + <Compile Include="TException.cs" /> + <Compile Include="TProcessor.cs" /> + <Compile Include="TProcessorFactory.cs" /> + <Compile Include="TPrototypeProcessorFactory.cs" /> + <Compile Include="Transport\TBufferedTransport.cs" /> + <Compile Include="Transport\TFramedTransport.cs" /> + <Compile Include="Transport\THttpClient.cs" /> + <Compile Include="Transport\THttpHandler.cs" /> + <Compile Include="Transport\TMemoryBuffer.cs" /> + <Compile Include="Transport\TNamedPipeClientTransport.cs" /> + <Compile Include="Transport\TNamedPipeServerTransport.cs" /> + <Compile Include="Transport\TServerSocket.cs" /> + <Compile Include="Transport\TServerTransport.cs" /> + <Compile Include="Transport\TSocket.cs" /> + <Compile Include="Transport\TSocketVersionizer.cs" /> + <Compile Include="Transport\TStreamTransport.cs" /> + <Compile Include="Transport\TTLSServerSocket.cs" /> + <Compile Include="Transport\TTLSSocket.cs" /> + <Compile Include="Transport\TTransport.cs" /> + <Compile Include="Transport\TTransportException.cs" /> + <Compile Include="Transport\TTransportFactory.cs" /> + <Compile Include="TSingletonProcessorFactory.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <None Include="thrift.snk" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> + <ProjectExtensions> + <VisualStudio AllowExistingFolder="true" /> + </ProjectExtensions> +</Project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/src/Thrift.sln b/src/jaegertracing/thrift/lib/csharp/src/Thrift.sln new file mode 100644 index 000000000..a29e46882 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Thrift.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "..\test\ThriftTest\ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMSBuildTask", "..\ThriftMSBuildTask\ThriftMSBuildTask.csproj", "{EC0A0231-66EA-4593-A792-C6CA3BB8668E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.45", "Thrift.45.csproj", "{EBCE35DA-CF6A-42BC-A357-A9C09B534299}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMVCTest", "..\test\ThriftMVCTest\ThriftMVCTest.csproj", "{891B4487-C7BA-427E-BBC8-4C596C229A10}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.Build.0 = Release|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.Build.0 = Release|Any CPU + {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.Build.0 = Release|Any CPU + {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.Build.0 = Release|Any CPU + {891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Thrift.csproj + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TBufferedTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TBufferedTransport.cs new file mode 100644 index 000000000..887098810 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TBufferedTransport.cs @@ -0,0 +1,194 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.IO; + +namespace Thrift.Transport +{ + public class TBufferedTransport : TTransport, IDisposable + { + private readonly int bufSize; + private readonly MemoryStream inputBuffer = new MemoryStream(0); + private readonly MemoryStream outputBuffer = new MemoryStream(0); + private readonly TTransport transport; + + public TBufferedTransport(TTransport transport, int bufSize = 1024) + { + if (transport == null) + throw new ArgumentNullException("transport"); + if (bufSize <= 0) + throw new ArgumentException("bufSize", "Buffer size must be a positive number."); + this.transport = transport; + this.bufSize = bufSize; + } + + public TTransport UnderlyingTransport + { + get + { + CheckNotDisposed(); + return transport; + } + } + + public override bool IsOpen + { + get + { + // We can legitimately throw here but be nice a bit. + // CheckNotDisposed(); + return !_IsDisposed && transport.IsOpen; + } + } + + public override void Open() + { + CheckNotDisposed(); + transport.Open(); + } + + public override void Close() + { + CheckNotDisposed(); + transport.Close(); + } + + public override int Read(byte[] buf, int off, int len) + { + CheckNotDisposed(); + ValidateBufferArgs(buf, off, len); + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + + if (inputBuffer.Capacity < bufSize) + inputBuffer.Capacity = bufSize; + + while (true) + { + int got = inputBuffer.Read(buf, off, len); + if (got > 0) + return got; + + inputBuffer.Seek(0, SeekOrigin.Begin); + inputBuffer.SetLength(inputBuffer.Capacity); + int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length); + inputBuffer.SetLength(filled); + if (filled == 0) + return 0; + } + } + + public override void Write(byte[] buf, int off, int len) + { + CheckNotDisposed(); + ValidateBufferArgs(buf, off, len); + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + // Relative offset from "off" argument + int offset = 0; + if (outputBuffer.Length > 0) + { + int capa = (int)(outputBuffer.Capacity - outputBuffer.Length); + int writeSize = capa <= len ? capa : len; + outputBuffer.Write(buf, off, writeSize); + offset += writeSize; + if (writeSize == capa) + { + transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length); + outputBuffer.SetLength(0); + } + } + while (len - offset >= bufSize) + { + transport.Write(buf, off + offset, bufSize); + offset += bufSize; + } + int remain = len - offset; + if (remain > 0) + { + if (outputBuffer.Capacity < bufSize) + outputBuffer.Capacity = bufSize; + outputBuffer.Write(buf, off + offset, remain); + } + } + + private void InternalFlush() + { + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + if (outputBuffer.Length > 0) + { + transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length); + outputBuffer.SetLength(0); + } + } + + public override void Flush() + { + CheckNotDisposed(); + InternalFlush(); + + transport.Flush(); + } + + public override IAsyncResult BeginFlush(AsyncCallback callback, object state) + { + CheckNotDisposed(); + InternalFlush(); + + return transport.BeginFlush( callback, state); + } + + public override void EndFlush(IAsyncResult asyncResult) + { + transport.EndFlush( asyncResult); + } + + + + protected void CheckNotDisposed() + { + if (_IsDisposed) + throw new ObjectDisposedException("TBufferedTransport"); + } + + #region " IDisposable Support " + protected bool _IsDisposed { get; private set; } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (inputBuffer != null) + inputBuffer.Dispose(); + if (outputBuffer != null) + outputBuffer.Dispose(); + if (transport != null) + transport.Dispose(); + } + } + _IsDisposed = true; + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TFramedTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TFramedTransport.cs new file mode 100644 index 000000000..a746a3223 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TFramedTransport.cs @@ -0,0 +1,205 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +using System; +using System.IO; + +namespace Thrift.Transport +{ + public class TFramedTransport : TTransport, IDisposable + { + private readonly TTransport transport; + private readonly MemoryStream writeBuffer = new MemoryStream(1024); + private readonly MemoryStream readBuffer = new MemoryStream(1024); + + private const int HeaderSize = 4; + private readonly byte[] headerBuf = new byte[HeaderSize]; + + public class Factory : TTransportFactory + { + public override TTransport GetTransport(TTransport trans) + { + return new TFramedTransport(trans); + } + } + + public TFramedTransport(TTransport transport) + { + if (transport == null) + throw new ArgumentNullException("transport"); + this.transport = transport; + InitWriteBuffer(); + } + + public override void Open() + { + CheckNotDisposed(); + transport.Open(); + } + + public override bool IsOpen + { + get + { + // We can legitimately throw here but be nice a bit. + // CheckNotDisposed(); + return !_IsDisposed && transport.IsOpen; + } + } + + public override void Close() + { + CheckNotDisposed(); + transport.Close(); + } + + public override int Read(byte[] buf, int off, int len) + { + CheckNotDisposed(); + ValidateBufferArgs(buf, off, len); + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + int got = readBuffer.Read(buf, off, len); + if (got > 0) + { + return got; + } + + // Read another frame of data + ReadFrame(); + + return readBuffer.Read(buf, off, len); + } + + private void ReadFrame() + { + transport.ReadAll(headerBuf, 0, HeaderSize); + int size = DecodeFrameSize(headerBuf); + + readBuffer.SetLength(size); + readBuffer.Seek(0, SeekOrigin.Begin); + byte[] buff = readBuffer.GetBuffer(); + transport.ReadAll(buff, 0, size); + } + + public override void Write(byte[] buf, int off, int len) + { + CheckNotDisposed(); + ValidateBufferArgs(buf, off, len); + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + if (writeBuffer.Length + (long)len > (long)int.MaxValue) + Flush(); + writeBuffer.Write(buf, off, len); + } + + private void InternalFlush() + { + CheckNotDisposed(); + if (!IsOpen) + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + byte[] buf = writeBuffer.GetBuffer(); + int len = (int)writeBuffer.Length; + int data_len = len - HeaderSize; + if (data_len < 0) + throw new System.InvalidOperationException(); // logic error actually + + // Inject message header into the reserved buffer space + EncodeFrameSize(data_len, buf); + + // Send the entire message at once + transport.Write(buf, 0, len); + + InitWriteBuffer(); + } + + public override void Flush() + { + CheckNotDisposed(); + InternalFlush(); + + transport.Flush(); + } + + public override IAsyncResult BeginFlush(AsyncCallback callback, object state) + { + CheckNotDisposed(); + InternalFlush(); + + return transport.BeginFlush( callback, state); + } + + public override void EndFlush(IAsyncResult asyncResult) + { + transport.EndFlush( asyncResult); + } + + private void InitWriteBuffer() + { + // Reserve space for message header to be put right before sending it out + writeBuffer.SetLength(HeaderSize); + writeBuffer.Seek(0, SeekOrigin.End); + } + + private static void EncodeFrameSize(int frameSize, byte[] buf) + { + buf[0] = (byte)(0xff & (frameSize >> 24)); + buf[1] = (byte)(0xff & (frameSize >> 16)); + buf[2] = (byte)(0xff & (frameSize >> 8)); + buf[3] = (byte)(0xff & (frameSize)); + } + + private static int DecodeFrameSize(byte[] buf) + { + return + ((buf[0] & 0xff) << 24) | + ((buf[1] & 0xff) << 16) | + ((buf[2] & 0xff) << 8) | + ((buf[3] & 0xff)); + } + + + private void CheckNotDisposed() + { + if (_IsDisposed) + throw new ObjectDisposedException("TFramedTransport"); + } + + #region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (readBuffer != null) + readBuffer.Dispose(); + if (writeBuffer != null) + writeBuffer.Dispose(); + if (transport != null) + transport.Dispose(); + } + } + _IsDisposed = true; + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpClient.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpClient.cs new file mode 100644 index 000000000..986799cd2 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpClient.cs @@ -0,0 +1,486 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Threading; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.IO.Compression; + +namespace Thrift.Transport +{ + public class THttpClient : TTransport, IDisposable + { + private readonly Uri uri; + private readonly X509Certificate[] certificates; + private Stream inputStream; + private MemoryStream outputStream = new MemoryStream(); + + // Timeouts in milliseconds + private int connectTimeout = 30000; + + private int readTimeout = 30000; + + private IDictionary<string, string> customHeaders = new Dictionary<string, string>(); + private string userAgent = "C#/THttpClient"; + +#if !SILVERLIGHT + private IWebProxy proxy = WebRequest.DefaultWebProxy; +#endif + + public THttpClient(Uri u) + : this(u, Enumerable.Empty<X509Certificate>()) + { + } + public THttpClient(Uri u, string userAgent) + : this(u, userAgent, Enumerable.Empty<X509Certificate>()) + { + } + + public THttpClient(Uri u, IEnumerable<X509Certificate> certificates) + { + uri = u; + this.certificates = (certificates ?? Enumerable.Empty<X509Certificate>()).ToArray(); + } + public THttpClient(Uri u, string userAgent, IEnumerable<X509Certificate> certificates) + { + uri = u; + this.userAgent = userAgent; + this.certificates = (certificates ?? Enumerable.Empty<X509Certificate>()).ToArray(); + } + + public int ConnectTimeout + { + set + { + connectTimeout = value; + } + } + + public int ReadTimeout + { + set + { + readTimeout = value; + } + } + + public IDictionary<string, string> CustomHeaders + { + get + { + return customHeaders; + } + } + +#if !SILVERLIGHT + public IWebProxy Proxy + { + set + { + proxy = value; + } + } +#endif + + public override bool IsOpen + { + get + { + return true; + } + } + + public override void Open() + { + } + + public override void Close() + { + if (inputStream != null) + { + inputStream.Close(); + inputStream = null; + } + if (outputStream != null) + { + outputStream.Close(); + outputStream = null; + } + } + + public override int Read(byte[] buf, int off, int len) + { + if (inputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); + } + + try + { + int ret = inputStream.Read(buf, off, len); + + if (ret == -1) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); + } + + return ret; + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); + } + } + + public override void Write(byte[] buf, int off, int len) + { + outputStream.Write(buf, off, len); + } + +#if !SILVERLIGHT + public override void Flush() + { + try + { + SendRequest(); + } + finally + { + outputStream = new MemoryStream(); + } + } + + private void SendRequest() + { + try + { + HttpWebRequest connection = CreateRequest(); + connection.Headers.Add("Accept-Encoding", "gzip, deflate"); + + byte[] data = outputStream.ToArray(); + connection.ContentLength = data.Length; + + using (Stream requestStream = connection.GetRequestStream()) + { + requestStream.Write(data, 0, data.Length); + + // Resolve HTTP hang that can happens after successive calls by making sure + // that we release the response and response stream. To support this, we copy + // the response to a memory stream. + using (var response = connection.GetResponse()) + { + using (var responseStream = response.GetResponseStream()) + { + // Copy the response to a memory stream so that we can + // cleanly close the response and response stream. + inputStream = new MemoryStream(); + byte[] buffer = new byte[8192]; // multiple of 4096 + int bytesRead; + while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) + { + inputStream.Write(buffer, 0, bytesRead); + } + inputStream.Seek(0, 0); + } + + var encodings = response.Headers.GetValues("Content-Encoding"); + if (encodings != null) + { + foreach (var encoding in encodings) + { + switch (encoding) + { + case "gzip": + DecompressGZipped(ref inputStream); + break; + case "deflate": + DecompressDeflated(ref inputStream); + break; + default: + break; + } + } + } + } + } + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); + } + catch (WebException wx) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx, wx); + } + } + + private void DecompressDeflated(ref Stream inputStream) + { + var tmp = new MemoryStream(); + using (var decomp = new DeflateStream(inputStream, CompressionMode.Decompress)) + { + decomp.CopyTo(tmp); + } + inputStream.Dispose(); + inputStream = tmp; + inputStream.Seek(0, 0); + } + + private void DecompressGZipped(ref Stream inputStream) + { + var tmp = new MemoryStream(); + using (var decomp = new GZipStream(inputStream, CompressionMode.Decompress)) + { + decomp.CopyTo(tmp); + } + inputStream.Dispose(); + inputStream = tmp; + inputStream.Seek(0, 0); + } +#endif + private HttpWebRequest CreateRequest() + { + HttpWebRequest connection = (HttpWebRequest)WebRequest.Create(uri); + + +#if !SILVERLIGHT + // Adding certificates through code is not supported with WP7 Silverlight + // see "Windows Phone 7 and Certificates_FINAL_121610.pdf" + connection.ClientCertificates.AddRange(certificates); + + if (connectTimeout > 0) + { + connection.Timeout = connectTimeout; + } + if (readTimeout > 0) + { + connection.ReadWriteTimeout = readTimeout; + } +#endif + // Make the request + connection.ContentType = "application/x-thrift"; + connection.Accept = "application/x-thrift"; + connection.UserAgent = userAgent; + connection.Method = "POST"; +#if !SILVERLIGHT + connection.ProtocolVersion = HttpVersion.Version10; +#endif + + //add custom headers here + foreach (KeyValuePair<string, string> item in customHeaders) + { +#if !SILVERLIGHT + connection.Headers.Add(item.Key, item.Value); +#else + connection.Headers[item.Key] = item.Value; +#endif + } + +#if !SILVERLIGHT + connection.Proxy = proxy; +#endif + + return connection; + } + + public override IAsyncResult BeginFlush(AsyncCallback callback, object state) + { + // Extract request and reset buffer + var data = outputStream.ToArray(); + + //requestBuffer_ = new MemoryStream(); + + try + { + // Create connection object + var flushAsyncResult = new FlushAsyncResult(callback, state); + flushAsyncResult.Connection = CreateRequest(); + + flushAsyncResult.Data = data; + + + flushAsyncResult.Connection.BeginGetRequestStream(GetRequestStreamCallback, flushAsyncResult); + return flushAsyncResult; + + } + catch (IOException iox) + { + throw new TTransportException(iox.ToString(), iox); + } + } + + public override void EndFlush(IAsyncResult asyncResult) + { + try + { + var flushAsyncResult = (FlushAsyncResult)asyncResult; + + if (!flushAsyncResult.IsCompleted) + { + var waitHandle = flushAsyncResult.AsyncWaitHandle; + waitHandle.WaitOne(); // blocking INFINITEly + waitHandle.Close(); + } + + if (flushAsyncResult.AsyncException != null) + { + throw flushAsyncResult.AsyncException; + } + } + finally + { + outputStream = new MemoryStream(); + } + + } + + private void GetRequestStreamCallback(IAsyncResult asynchronousResult) + { + var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState; + try + { + var reqStream = flushAsyncResult.Connection.EndGetRequestStream(asynchronousResult); + reqStream.Write(flushAsyncResult.Data, 0, flushAsyncResult.Data.Length); + reqStream.Flush(); + reqStream.Close(); + + // Start the asynchronous operation to get the response + flushAsyncResult.Connection.BeginGetResponse(GetResponseCallback, flushAsyncResult); + } + catch (Exception exception) + { + flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception); + flushAsyncResult.UpdateStatusToComplete(); + flushAsyncResult.NotifyCallbackWhenAvailable(); + } + } + + private void GetResponseCallback(IAsyncResult asynchronousResult) + { + var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState; + try + { + inputStream = flushAsyncResult.Connection.EndGetResponse(asynchronousResult).GetResponseStream(); + } + catch (Exception exception) + { + flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception); + } + flushAsyncResult.UpdateStatusToComplete(); + flushAsyncResult.NotifyCallbackWhenAvailable(); + } + + // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx + class FlushAsyncResult : IAsyncResult + { + private volatile Boolean _isCompleted; + private ManualResetEvent _evt; + private readonly AsyncCallback _cbMethod; + private readonly object _state; + + public FlushAsyncResult(AsyncCallback cbMethod, object state) + { + _cbMethod = cbMethod; + _state = state; + } + + internal byte[] Data { get; set; } + internal HttpWebRequest Connection { get; set; } + internal TTransportException AsyncException { get; set; } + + public object AsyncState + { + get { return _state; } + } + public WaitHandle AsyncWaitHandle + { + get { return GetEvtHandle(); } + } + public bool CompletedSynchronously + { + get { return false; } + } + public bool IsCompleted + { + get { return _isCompleted; } + } + private readonly object _locker = new object(); + private ManualResetEvent GetEvtHandle() + { + lock (_locker) + { + if (_evt == null) + { + _evt = new ManualResetEvent(false); + } + if (_isCompleted) + { + _evt.Set(); + } + } + return _evt; + } + internal void UpdateStatusToComplete() + { + _isCompleted = true; //1. set _iscompleted to true + lock (_locker) + { + if (_evt != null) + { + _evt.Set(); //2. set the event, when it exists + } + } + } + + internal void NotifyCallbackWhenAvailable() + { + if (_cbMethod != null) + { + _cbMethod(this); + } + } + } + + #region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (inputStream != null) + inputStream.Dispose(); + if (outputStream != null) + outputStream.Dispose(); + } + } + _IsDisposed = true; + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpHandler.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpHandler.cs new file mode 100644 index 000000000..4115ef95a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpHandler.cs @@ -0,0 +1,102 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ + +using System; +using System.Web; +using System.Net; +using System.IO; + +using Thrift.Protocol; + +namespace Thrift.Transport +{ + public class THttpHandler : IHttpHandler + { + protected TProcessor processor; + + protected TProtocolFactory inputProtocolFactory; + protected TProtocolFactory outputProtocolFactory; + + protected const string contentType = "application/x-thrift"; + protected System.Text.Encoding encoding = System.Text.Encoding.UTF8; + + public THttpHandler(TProcessor processor) + : this(processor, new TBinaryProtocol.Factory()) + { + + } + + public THttpHandler(TProcessor processor, TProtocolFactory protocolFactory) + : this(processor, protocolFactory, protocolFactory) + { + + } + + public THttpHandler(TProcessor processor, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory) + { + this.processor = processor; + this.inputProtocolFactory = inputProtocolFactory; + this.outputProtocolFactory = outputProtocolFactory; + } + + public void ProcessRequest(HttpListenerContext context) + { + context.Response.ContentType = contentType; + context.Response.ContentEncoding = encoding; + ProcessRequest(context.Request.InputStream, context.Response.OutputStream); + } + + public void ProcessRequest(HttpContext context) + { + context.Response.ContentType = contentType; + context.Response.ContentEncoding = encoding; + ProcessRequest(context.Request.InputStream, context.Response.OutputStream); + } + + public void ProcessRequest(Stream input, Stream output) + { + TTransport transport = new TStreamTransport(input,output); + + try + { + var inputProtocol = inputProtocolFactory.GetProtocol(transport); + var outputProtocol = outputProtocolFactory.GetProtocol(transport); + + while (processor.Process(inputProtocol, outputProtocol)) + { + } + } + catch (TTransportException) + { + // Client died, just move on + } + finally + { + transport.Close(); + } + } + + public bool IsReusable + { + get { return true; } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs new file mode 100644 index 000000000..e491f32cb --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs @@ -0,0 +1,97 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System.Threading.Tasks; +using System.Web; +using Thrift.Protocol; + +namespace Thrift.Transport +{ + /// <summary> + /// An async task based HTTP handler for processing thrift services. + /// </summary> + public class THttpTaskAsyncHandler : HttpTaskAsyncHandler + { + private readonly TAsyncProcessor _processor; + private readonly TProtocolFactory _inputProtocolFactory; + private readonly TProtocolFactory _outputProtocolFactory; + + /// <summary> + /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class + /// using the <see cref="TBinaryProtocol.Factory"/> for both input and output streams. + /// </summary> + /// <param name="processor">The async processor implementation.</param> + public THttpTaskAsyncHandler(TAsyncProcessor processor) + : this(processor, new TBinaryProtocol.Factory()) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class + /// using <paramref name="protocolFactory"/> for both input and output streams. + /// </summary> + /// <param name="processor">The async processor implementation.</param> + /// <param name="protocolFactory">The protocol factory.</param> + public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory protocolFactory) + : this(processor, protocolFactory, protocolFactory) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class. + /// </summary> + /// <param name="processor">The async processor implementation.</param> + /// <param name="inputProtocolFactory">The input protocol factory.</param> + /// <param name="outputProtocolFactory">The output protocol factory.</param> + public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory) + { + _processor = processor; + _inputProtocolFactory = inputProtocolFactory; + _outputProtocolFactory = outputProtocolFactory; + } + + public override async Task ProcessRequestAsync(HttpContext context) + { + var transport = new TStreamTransport(context.Request.InputStream, context.Response.OutputStream); + + try + { + var input = _inputProtocolFactory.GetProtocol(transport); + var output = _outputProtocolFactory.GetProtocol(transport); + + while (await _processor.ProcessAsync(input, output)) + { + } + } + catch (TTransportException) + { + // Client died, just move on + } + finally + { + transport.Close(); + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TMemoryBuffer.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TMemoryBuffer.cs new file mode 100644 index 000000000..303d08329 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TMemoryBuffer.cs @@ -0,0 +1,117 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.IO; +using System.Reflection; +using Thrift.Protocol; + +namespace Thrift.Transport +{ + public class TMemoryBuffer : TTransport + { + + private readonly MemoryStream byteStream; + + public TMemoryBuffer() + { + byteStream = new MemoryStream(); + } + + public TMemoryBuffer(byte[] buf) + { + byteStream = new MemoryStream(buf); + } + + public override void Open() + { + /** do nothing **/ + } + + public override void Close() + { + /** do nothing **/ + } + + public override int Read(byte[] buf, int off, int len) + { + return byteStream.Read(buf, off, len); + } + + public override void Write(byte[] buf, int off, int len) + { + byteStream.Write(buf, off, len); + } + + public byte[] GetBuffer() + { + return byteStream.ToArray(); + } + + + public override bool IsOpen + { + get { return true; } + } + + public static byte[] Serialize(TAbstractBase s) + { + var t = new TMemoryBuffer(); + var p = new TBinaryProtocol(t); + + s.Write(p); + + return t.GetBuffer(); + } + + public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase + { + var trans = new TMemoryBuffer(buf); + var p = new TBinaryProtocol(trans); + if (typeof(TBase).IsAssignableFrom(typeof(T))) + { + var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public); + var t = Activator.CreateInstance<T>(); + method.Invoke(t, new object[] { p }); + return t; + } + else + { + var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public); + return (T)method.Invoke(null, new object[] { p }); + } + } + + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (byteStream != null) + byteStream.Dispose(); + } + } + _IsDisposed = true; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeClientTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeClientTransport.cs new file mode 100644 index 000000000..49a50aa5b --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeClientTransport.cs @@ -0,0 +1,111 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.IO.Pipes; +using System.Threading; + +namespace Thrift.Transport +{ + public class TNamedPipeClientTransport : TTransport + { + private NamedPipeClientStream client; + private string ServerName; + private string PipeName; + private int ConnectTimeout; + + public TNamedPipeClientTransport(string pipe, int timeout = Timeout.Infinite) + { + ServerName = "."; + PipeName = pipe; + ConnectTimeout = timeout; + } + + public TNamedPipeClientTransport(string server, string pipe, int timeout = Timeout.Infinite) + { + ServerName = (server != "") ? server : "."; + PipeName = pipe; + ConnectTimeout = timeout; + } + + public override bool IsOpen + { + get { return client != null && client.IsConnected; } + } + + public override void Open() + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); + } + client = new NamedPipeClientStream(ServerName, PipeName, PipeDirection.InOut, PipeOptions.None); + client.Connect(ConnectTimeout); + } + + public override void Close() + { + if (client != null) + { + client.Close(); + client = null; + } + } + + public override int Read(byte[] buf, int off, int len) + { + if (client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + return client.Read(buf, off, len); + } + + public override void Write(byte[] buf, int off, int len) + { + if (client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // if necessary, send the data in chunks + // there's a system limit around 0x10000 bytes that we hit otherwise + // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." + var nBytes = Math.Min(len, 15 * 4096); // 16 would exceed the limit + while (nBytes > 0) + { + client.Write(buf, off, nBytes); + + off += nBytes; + len -= nBytes; + nBytes = Math.Min(len, nBytes); + } + } + + protected override void Dispose(bool disposing) + { + client.Dispose(); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeServerTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeServerTransport.cs new file mode 100644 index 000000000..32215cfc1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TNamedPipeServerTransport.cs @@ -0,0 +1,296 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.IO.Pipes; +using System.Threading; +using System.Security.Principal; + +namespace Thrift.Transport +{ + public class TNamedPipeServerTransport : TServerTransport + { + /// <summary> + /// This is the address of the Pipe on the localhost. + /// </summary> + private readonly string pipeAddress; + private NamedPipeServerStream stream = null; + private bool asyncMode = true; + + public TNamedPipeServerTransport(string pipeAddress) + { + this.pipeAddress = pipeAddress; + } + + public override void Listen() + { + // nothing to do here + } + + public override void Close() + { + if (stream != null) + { + try + { + stream.Close(); + stream.Dispose(); + } + finally + { + stream = null; + } + } + } + + private void EnsurePipeInstance() + { + if (stream == null) + { + var direction = PipeDirection.InOut; + var maxconn = NamedPipeServerStream.MaxAllowedServerInstances; + var mode = PipeTransmissionMode.Byte; + var options = asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; + const int INBUF_SIZE = 4096; + const int OUTBUF_SIZE = 4096; + + // security + var security = new PipeSecurity(); + security.AddAccessRule( + new PipeAccessRule( + new SecurityIdentifier(WellKnownSidType.WorldSid, null), + PipeAccessRights.Read | PipeAccessRights.Write | PipeAccessRights.Synchronize | PipeAccessRights.CreateNewInstance, + System.Security.AccessControl.AccessControlType.Allow + ) + ); + + try + { + stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security); + } + catch (NotImplementedException) // Mono still does not support async, fallback to sync + { + if (asyncMode) + { + options &= (~PipeOptions.Asynchronous); + stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security); + asyncMode = false; + } + else + { + throw; + } + } + + } + } + + protected override TTransport AcceptImpl() + { + try + { + EnsurePipeInstance(); + + if (asyncMode) + { + var evt = new ManualResetEvent(false); + Exception eOuter = null; + + stream.BeginWaitForConnection(asyncResult => + { + try + { + if (stream != null) + stream.EndWaitForConnection(asyncResult); + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); + } + catch (Exception e) + { + if (stream != null) + eOuter = e; + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); + } + evt.Set(); + }, null); + + evt.WaitOne(); + + if (eOuter != null) + throw eOuter; // rethrow exception + } + else + { + stream.WaitForConnection(); + } + + var trans = new ServerTransport(stream,asyncMode); + stream = null; // pass ownership to ServerTransport + return trans; + } + catch (TTransportException) + { + Close(); + throw; + } + catch (Exception e) + { + Close(); + throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message, e); + } + } + + private class ServerTransport : TTransport + { + private NamedPipeServerStream stream; + private bool asyncMode; + + public ServerTransport(NamedPipeServerStream stream, bool asyncMode) + { + this.stream = stream; + this.asyncMode = asyncMode; + } + + public override bool IsOpen + { + get { return stream != null && stream.IsConnected; } + } + + public override void Open() + { + } + + public override void Close() + { + if (stream != null) + stream.Close(); + } + + public override int Read(byte[] buf, int off, int len) + { + if (stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (asyncMode) + { + Exception eOuter = null; + var evt = new ManualResetEvent(false); + int retval = 0; + + stream.BeginRead(buf, off, len, asyncResult => + { + try + { + if (stream != null) + retval = stream.EndRead(asyncResult); + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); + } + catch (Exception e) + { + if (stream != null) + eOuter = e; + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); + } + evt.Set(); + }, null); + + evt.WaitOne(); + + if (eOuter != null) + throw eOuter; // rethrow exception + else + return retval; + } + else + { + return stream.Read(buf, off, len); + } + } + + public override void Write(byte[] buf, int off, int len) + { + if (stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // if necessary, send the data in chunks + // there's a system limit around 0x10000 bytes that we hit otherwise + // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." + var nBytes = Math.Min(len, 15 * 4096); // 16 would exceed the limit + while (nBytes > 0) + { + + if (asyncMode) + { + Exception eOuter = null; + var evt = new ManualResetEvent(false); + + stream.BeginWrite(buf, off, nBytes, asyncResult => + { + try + { + if (stream != null) + stream.EndWrite(asyncResult); + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); + } + catch (Exception e) + { + if (stream != null) + eOuter = e; + else + eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); + } + evt.Set(); + }, null); + + evt.WaitOne(); + + if (eOuter != null) + throw eOuter; // rethrow exception + } + else + { + stream.Write(buf, off, nBytes); + } + + off += nBytes; + len -= nBytes; + nBytes = Math.Min(len, nBytes); + } + } + + protected override void Dispose(bool disposing) + { + if (stream != null) + stream.Dispose(); + } + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerSocket.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerSocket.cs new file mode 100644 index 000000000..d8ec62ab3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerSocket.cs @@ -0,0 +1,176 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Net.Sockets; + + +namespace Thrift.Transport +{ + public class TServerSocket : TServerTransport + { + /// <summary> + /// Underlying server with socket. + /// </summary> + private TcpListener server = null; + + /// <summary> + /// Port to listen on. + /// </summary> + private int port = 0; + + /// <summary> + /// Timeout for client sockets from accept. + /// </summary> + private int clientTimeout = 0; + + /// <summary> + /// Whether or not to wrap new TSocket connections in buffers. + /// </summary> + private bool useBufferedSockets = false; + + /// <summary> + /// Creates a server socket from underlying socket object. + /// </summary> + public TServerSocket(TcpListener listener) + : this(listener, 0) + { + } + + /// <summary> + /// Creates a server socket from underlying socket object. + /// </summary> + public TServerSocket(TcpListener listener, int clientTimeout) + { + this.server = listener; + this.clientTimeout = clientTimeout; + } + + /// <summary> + /// Creates just a port listening server socket. + /// </summary> + public TServerSocket(int port) + : this(port, 0) + { + } + + /// <summary> + /// Creates just a port listening server socket. + /// </summary> + public TServerSocket(int port, int clientTimeout) + : this(port, clientTimeout, false) + { + } + + public TServerSocket(int port, int clientTimeout, bool useBufferedSockets) + { + this.port = port; + this.clientTimeout = clientTimeout; + this.useBufferedSockets = useBufferedSockets; + try + { + // Make server socket + this.server = TSocketVersionizer.CreateTcpListener(this.port); + this.server.Server.NoDelay = true; + } + catch (Exception ex) + { + server = null; + throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex); + } + } + + public override void Listen() + { + // Make sure not to block on accept + if (server != null) + { + try + { + server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx); + } + } + } + + protected override TTransport AcceptImpl() + { + if (server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + try + { + TSocket result2 = null; + TcpClient result = server.AcceptTcpClient(); + try + { + result2 = new TSocket(result); + result2.Timeout = clientTimeout; + if (useBufferedSockets) + { + TBufferedTransport result3 = new TBufferedTransport(result2); + return result3; + } + else + { + return result2; + } + } + catch (System.Exception) + { + // If a TSocket was successfully created, then let + // it do proper cleanup of the TcpClient object. + if (result2 != null) + result2.Dispose(); + else // Otherwise, clean it up ourselves. + ((IDisposable)result).Dispose(); + throw; + } + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString(), ex); + } + } + + public override void Close() + { + if (server != null) + { + try + { + server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex, ex); + } + server = null; + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerTransport.cs new file mode 100644 index 000000000..e63880be1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TServerTransport.cs @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Transport +{ + public abstract class TServerTransport + { + public abstract void Listen(); + public abstract void Close(); + protected abstract TTransport AcceptImpl(); + + public TTransport Accept() + { + TTransport transport = AcceptImpl(); + if (transport == null) + { + throw new TTransportException("accept() may not return NULL"); + } + return transport; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TSilverlightSocket.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSilverlightSocket.cs new file mode 100644 index 000000000..40469ab40 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSilverlightSocket.cs @@ -0,0 +1,393 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +/* only for silverlight */ +#if SILVERLIGHT + +using System; +using System.Net.Sockets; +using System.IO; +using System.Net; +using System.Threading; + +namespace Thrift.Transport +{ + public class TSilverlightSocket : TTransport + { + Socket socket = null; + static ManualResetEvent readAsyncComplete = new ManualResetEvent(false); + public event EventHandler<SocketAsyncEventArgs> connectHandler = null; + + // memory stream for write cache. + private MemoryStream outputStream = new MemoryStream(); + + private string host = null; + private int port = 0; + private int timeout = 0; + + // constructor + public TSilverlightSocket(string host, int port) + : this(host, port, 0) + { + } + + // constructor + public TSilverlightSocket(string host, int port, int timeout) + { + this.host = host; + this.port = port; + this.timeout = timeout; + + InitSocket(); + } + + private void InitSocket() + { + // Create a stream-based, TCP socket using the InterNetwork Address Family. + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + socket.NoDelay = true; + } + + public int Timeout + { + set + { + timeout = value; + } + } + + public string Host + { + get + { + return host; + } + } + + public int Port + { + get + { + return port; + } + } + + public override bool IsOpen + { + get + { + if (socket == null) + { + return false; + } + + return socket.Connected; + } + } + + public override void Open() + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (string.IsNullOrEmpty(host)) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (socket == null) + { + InitSocket(); + } + + if (timeout == 0) // no timeout -> infinite + { + timeout = 10000; // set a default timeout for WP. + } + + { + // Create DnsEndPoint. The hostName and port are passed in to this method. + DnsEndPoint hostEntry = new DnsEndPoint(this.host, this.port); + + // Create a SocketAsyncEventArgs object to be used in the connection request + SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); + socketEventArg.RemoteEndPoint = hostEntry; + + // Inline event handler for the Completed event. + // Note: This event handler was implemented inline in order to make this method self-contained. + socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) + { + if (connectHandler != null) + { + connectHandler(this, e); + } + }); + + // Make an asynchronous Connect request over the socket + socket.ConnectAsync(socketEventArg); + } + } + + public override int Read(byte[] buf, int off, int len) + { + bool _timeout = true; + string _error = null; + int _recvBytes = -1; + + if (socket == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Socket is not open"); + } + + // Create SocketAsyncEventArgs context object + SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); + socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; + + // Setup the buffer to receive the data + socketEventArg.SetBuffer(buf, off, len); + + // Inline event handler for the Completed event. + // Note: This even handler was implemented inline in order to make + // this method self-contained. + socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) + { + _timeout = false; + + if (e.SocketError == SocketError.Success) + { + _recvBytes = e.BytesTransferred; + } + else + { + _error = e.SocketError.ToString(); + } + + readAsyncComplete.Set(); + }); + + // Sets the state of the event to nonsignaled, causing threads to block + readAsyncComplete.Reset(); + + // Make an asynchronous Receive request over the socket + socket.ReceiveAsync(socketEventArg); + + // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds. + // If no response comes back within this time then proceed + readAsyncComplete.WaitOne(this.timeout); + + if (_timeout) + { + throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Socket recv timeout"); + } + + if (_error != null) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, _error); + } + + return _recvBytes; + } + + public override void Write(byte[] buf, int off, int len) + { + outputStream.Write(buf, off, len); + } + + private void beginFlush_Completed(object sender, SocketAsyncEventArgs e) + { + FlushAsyncResult flushAsyncResult = e.UserToken as FlushAsyncResult; + flushAsyncResult.UpdateStatusToComplete(); + flushAsyncResult.NotifyCallbackWhenAvailable(); + + if (e.SocketError != SocketError.Success) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.SocketError.ToString()); + } + } + + public override IAsyncResult BeginFlush(AsyncCallback callback, object state) + { + // Extract request and reset buffer + byte[] data = outputStream.ToArray(); + + FlushAsyncResult flushAsyncResult = new FlushAsyncResult(callback, state); + + SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); + socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; + socketEventArg.UserToken = flushAsyncResult; + + socketEventArg.Completed += beginFlush_Completed; + socketEventArg.SetBuffer(data, 0, data.Length); + + socket.SendAsync(socketEventArg); + + return flushAsyncResult; + } + + public override void EndFlush(IAsyncResult asyncResult) + { + try + { + var flushAsyncResult = (FlushAsyncResult)asyncResult; + + if (!flushAsyncResult.IsCompleted) + { + var waitHandle = flushAsyncResult.AsyncWaitHandle; + waitHandle.WaitOne(); + waitHandle.Close(); + } + + if (flushAsyncResult.AsyncException != null) + { + throw flushAsyncResult.AsyncException; + } + } + finally + { + outputStream = new MemoryStream(); + } + } + + // Copy from impl from THttpClient.cs + // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx + class FlushAsyncResult : IAsyncResult + { + private volatile Boolean _isCompleted; + private ManualResetEvent _evt; + private readonly AsyncCallback _cbMethod; + private readonly object _state; + + public FlushAsyncResult(AsyncCallback cbMethod, object state) + { + _cbMethod = cbMethod; + _state = state; + } + + internal byte[] Data { get; set; } + internal Socket Connection { get; set; } + internal TTransportException AsyncException { get; set; } + + public object AsyncState + { + get { return _state; } + } + + public WaitHandle AsyncWaitHandle + { + get { return GetEvtHandle(); } + } + + public bool CompletedSynchronously + { + get { return false; } + } + + public bool IsCompleted + { + get { return _isCompleted; } + } + + private readonly object _locker = new object(); + + private ManualResetEvent GetEvtHandle() + { + lock (_locker) + { + if (_evt == null) + { + _evt = new ManualResetEvent(false); + } + if (_isCompleted) + { + _evt.Set(); + } + } + return _evt; + } + + internal void UpdateStatusToComplete() + { + _isCompleted = true; //1. set _iscompleted to true + lock (_locker) + { + if (_evt != null) + { + _evt.Set(); //2. set the event, when it exists + } + } + } + + internal void NotifyCallbackWhenAvailable() + { + if (_cbMethod != null) + { + _cbMethod(this); + } + } + } + + public override void Close() + { + if (socket != null) + { + socket.Close(); + socket = null; + } + } + +#region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (outputStream != null) + { + outputStream.Dispose(); + } + outputStream = null; + if (socket != null) + { + ((IDisposable)socket).Dispose(); + } + } + } + _IsDisposed = true; + } +#endregion + } +} + + +#endif diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocket.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocket.cs new file mode 100644 index 000000000..d8fa335ad --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocket.cs @@ -0,0 +1,245 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Net.Sockets; + +namespace Thrift.Transport +{ + public class TSocket : TStreamTransport + { + private TcpClient client = null; + private string host = null; + private int port = 0; + private int timeout = 0; + + public TSocket(TcpClient client) + { + this.client = client; + + if (IsOpen) + { + inputStream = client.GetStream(); + outputStream = client.GetStream(); + } + } + + public TSocket(string host, int port) + : this(host, port, 0) + { + } + + public TSocket(string host, int port, int timeout) + { + this.host = host; + this.port = port; + this.timeout = timeout; + + InitSocket(); + } + + private void InitSocket() + { + this.client = TSocketVersionizer.CreateTcpClient(); + this.client.ReceiveTimeout = client.SendTimeout = timeout; + this.client.Client.NoDelay = true; + } + + public int Timeout + { + set + { + client.ReceiveTimeout = client.SendTimeout = timeout = value; + } + } + + public TcpClient TcpClient + { + get + { + return client; + } + } + + public string Host + { + get + { + return host; + } + } + + public int Port + { + get + { + return port; + } + } + + public override bool IsOpen + { + get + { + if (client == null) + { + return false; + } + + return client.Connected; + } + } + + public override void Open() + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (string.IsNullOrEmpty(host)) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (client == null) + { + InitSocket(); + } + + if (timeout == 0) // no timeout -> infinite + { + client.Connect(host, port); + } + else // we have a timeout -> use it + { + ConnectHelper hlp = new ConnectHelper(client); + IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); + bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; + if (!bConnected) + { + lock (hlp.Mutex) + { + if (hlp.CallbackDone) + { + asyncres.AsyncWaitHandle.Close(); + client.Close(); + } + else + { + hlp.DoCleanup = true; + client = null; + } + } + throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); + } + } + + inputStream = client.GetStream(); + outputStream = client.GetStream(); + } + + + static void ConnectCallback(IAsyncResult asyncres) + { + ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; + lock (hlp.Mutex) + { + hlp.CallbackDone = true; + + try + { + if (hlp.Client.Client != null) + hlp.Client.EndConnect(asyncres); + } + catch (Exception) + { + // catch that away + } + + if (hlp.DoCleanup) + { + try + { + asyncres.AsyncWaitHandle.Close(); + } + catch (Exception) { } + + try + { + if (hlp.Client is IDisposable) + ((IDisposable)hlp.Client).Dispose(); + } + catch (Exception) { } + hlp.Client = null; + } + } + } + + private class ConnectHelper + { + public object Mutex = new object(); + public bool DoCleanup = false; + public bool CallbackDone = false; + public TcpClient Client; + public ConnectHelper(TcpClient client) + { + Client = client; + } + } + + public override void Close() + { + base.Close(); + if (client != null) + { + client.Close(); + client = null; + } + } + + #region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (client != null) + ((IDisposable)client).Dispose(); + base.Dispose(disposing); + } + } + _IsDisposed = true; + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocketVersionizer.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocketVersionizer.cs new file mode 100644 index 000000000..8c2f8e995 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TSocketVersionizer.cs @@ -0,0 +1,78 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +#if NET45 +using System.Threading.Tasks; +#endif + +namespace Thrift.Transport +{ + /// <summary> + /// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of + /// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections. + /// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used. + /// </summary> + internal static class TSocketVersionizer + { + /// <summary> + /// Creates a TcpClient according to the capabilities of the used framework. + /// </summary> + internal static TcpClient CreateTcpClient() + { + TcpClient client = null; + +#if NET45 + client = new TcpClient(AddressFamily.InterNetworkV6); + client.Client.DualMode = true; +#else + client = new TcpClient(AddressFamily.InterNetwork); +#endif + + return client; + } + + /// <summary> + /// Creates a TcpListener according to the capabilities of the used framework. + /// </summary> + internal static TcpListener CreateTcpListener(Int32 port) + { + TcpListener listener = null; + +#if NET45 + listener = new TcpListener(System.Net.IPAddress.IPv6Any, port); + listener.Server.DualMode = true; +#else + + listener = new TcpListener(System.Net.IPAddress.Any, port); +#endif + + return listener; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TStreamTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TStreamTransport.cs new file mode 100644 index 000000000..304599faa --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TStreamTransport.cs @@ -0,0 +1,128 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.IO; + +namespace Thrift.Transport +{ + public class TStreamTransport : TTransport + { + protected Stream inputStream; + protected Stream outputStream; + + protected TStreamTransport() + { + } + + public TStreamTransport(Stream inputStream, Stream outputStream) + { + this.inputStream = inputStream; + this.outputStream = outputStream; + } + + public Stream OutputStream + { + get { return outputStream; } + } + + public Stream InputStream + { + get { return inputStream; } + } + + public override bool IsOpen + { + get { return true; } + } + + public override void Open() + { + } + + public override void Close() + { + if (inputStream != null) + { + inputStream.Close(); + inputStream = null; + } + if (outputStream != null) + { + outputStream.Close(); + outputStream = null; + } + } + + public override int Read(byte[] buf, int off, int len) + { + if (inputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot read from null inputstream"); + } + + return inputStream.Read(buf, off, len); + } + + public override void Write(byte[] buf, int off, int len) + { + if (outputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot write to null outputstream"); + } + + outputStream.Write(buf, off, len); + } + + public override void Flush() + { + if (outputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot flush null outputstream"); + } + + outputStream.Flush(); + } + + + #region " IDisposable Support " + private bool _IsDisposed; + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_IsDisposed) + { + if (disposing) + { + if (InputStream != null) + InputStream.Dispose(); + if (OutputStream != null) + OutputStream.Dispose(); + } + } + _IsDisposed = true; + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSServerSocket.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSServerSocket.cs new file mode 100644 index 000000000..716a97ca8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSServerSocket.cs @@ -0,0 +1,223 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; + +namespace Thrift.Transport +{ + /// <summary> + /// SSL Server Socket Wrapper Class + /// </summary> + public class TTLSServerSocket : TServerTransport + { + /// <summary> + /// Underlying tcp server + /// </summary> + private TcpListener server = null; + + /// <summary> + /// The port where the socket listen + /// </summary> + private int port = 0; + + /// <summary> + /// Timeout for the created server socket + /// </summary> + private readonly int clientTimeout; + + /// <summary> + /// Whether or not to wrap new TSocket connections in buffers + /// </summary> + private bool useBufferedSockets = false; + + /// <summary> + /// The servercertificate with the private- and public-key + /// </summary> + private X509Certificate serverCertificate; + + /// <summary> + /// The function to validate the client certificate. + /// </summary> + private RemoteCertificateValidationCallback clientCertValidator; + + /// <summary> + /// The function to determine which certificate to use. + /// </summary> + private LocalCertificateSelectionCallback localCertificateSelectionCallback; + + /// <summary> + /// The SslProtocols value that represents the protocol used for authentication. + /// </summary> + private readonly SslProtocols sslProtocols; + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class. + /// </summary> + /// <param name="port">The port where the server runs.</param> + /// <param name="certificate">The certificate object.</param> + public TTLSServerSocket(int port, X509Certificate2 certificate) + : this(port, 0, certificate) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class. + /// </summary> + /// <param name="port">The port where the server runs.</param> + /// <param name="clientTimeout">Send/receive timeout.</param> + /// <param name="certificate">The certificate object.</param> + public TTLSServerSocket(int port, int clientTimeout, X509Certificate2 certificate) + : this(port, clientTimeout, false, certificate) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class. + /// </summary> + /// <param name="port">The port where the server runs.</param> + /// <param name="clientTimeout">Send/receive timeout.</param> + /// <param name="useBufferedSockets">If set to <c>true</c> [use buffered sockets].</param> + /// <param name="certificate">The certificate object.</param> + /// <param name="clientCertValidator">The certificate validator.</param> + /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param> + /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param> + public TTLSServerSocket( + int port, + int clientTimeout, + bool useBufferedSockets, + X509Certificate2 certificate, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+. + SslProtocols sslProtocols = SslProtocols.Tls) + { + if (!certificate.HasPrivateKey) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key"); + } + + this.port = port; + this.clientTimeout = clientTimeout; + this.serverCertificate = certificate; + this.useBufferedSockets = useBufferedSockets; + this.clientCertValidator = clientCertValidator; + this.localCertificateSelectionCallback = localCertificateSelectionCallback; + this.sslProtocols = sslProtocols; + try + { + // Create server socket + this.server = TSocketVersionizer.CreateTcpListener(this.port); + this.server.Server.NoDelay = true; + } + catch (Exception ex) + { + server = null; + throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex); + } + } + + /// <summary> + /// Starts the server. + /// </summary> + public override void Listen() + { + // Make sure accept is not blocking + if (this.server != null) + { + try + { + this.server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx); + } + } + } + + /// <summary> + /// Callback for Accept Implementation + /// </summary> + /// <returns> + /// TTransport-object. + /// </returns> + protected override TTransport AcceptImpl() + { + if (this.server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + TcpClient client = this.server.AcceptTcpClient(); + client.SendTimeout = client.ReceiveTimeout = this.clientTimeout; + + //wrap the client in an SSL Socket passing in the SSL cert + TTLSSocket socket = new TTLSSocket( + client, + this.serverCertificate, + true, + this.clientCertValidator, + this.localCertificateSelectionCallback, + this.sslProtocols); + + socket.setupTLS(); + + if (useBufferedSockets) + { + TBufferedTransport trans = new TBufferedTransport(socket); + return trans; + } + else + { + return socket; + } + + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString(), ex); + } + } + + /// <summary> + /// Stops the Server + /// </summary> + public override void Close() + { + if (this.server != null) + { + try + { + this.server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex, ex); + } + this.server = null; + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSSocket.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSSocket.cs new file mode 100644 index 000000000..06286dc8b --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTLSSocket.cs @@ -0,0 +1,445 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; + +namespace Thrift.Transport +{ + /// <summary> + /// SSL Socket Wrapper class + /// </summary> + public class TTLSSocket : TStreamTransport + { + /// <summary> + /// Internal TCP Client + /// </summary> + private TcpClient client; + + /// <summary> + /// The host + /// </summary> + private string host; + + /// <summary> + /// The port + /// </summary> + private int port; + + /// <summary> + /// The timeout for the connection + /// </summary> + private int timeout; + + /// <summary> + /// Internal SSL Stream for IO + /// </summary> + private SslStream secureStream; + + /// <summary> + /// Defines wheter or not this socket is a server socket<br/> + /// This is used for the TLS-authentication + /// </summary> + private bool isServer; + + /// <summary> + /// The certificate + /// </summary> + private X509Certificate certificate; + + /// <summary> + /// User defined certificate validator. + /// </summary> + private RemoteCertificateValidationCallback certValidator; + + /// <summary> + /// The function to determine which certificate to use. + /// </summary> + private LocalCertificateSelectionCallback localCertificateSelectionCallback; + + /// <summary> + /// The SslProtocols value that represents the protocol used for authentication.SSL protocols to be used. + /// </summary> + private readonly SslProtocols sslProtocols; + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSSocket"/> class. + /// </summary> + /// <param name="client">An already created TCP-client</param> + /// <param name="certificate">The certificate.</param> + /// <param name="isServer">if set to <c>true</c> [is server].</param> + /// <param name="certValidator">User defined cert validator.</param> + /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param> + /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param> + public TTLSSocket( + TcpClient client, + X509Certificate certificate, + bool isServer = false, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+. + SslProtocols sslProtocols = SslProtocols.Tls) + { + this.client = client; + this.certificate = certificate; + this.certValidator = certValidator; + this.localCertificateSelectionCallback = localCertificateSelectionCallback; + this.sslProtocols = sslProtocols; + this.isServer = isServer; + if (isServer && certificate == null) + { + throw new ArgumentException("TTLSSocket needs certificate to be used for server", "certificate"); + } + + if (IsOpen) + { + base.inputStream = client.GetStream(); + base.outputStream = client.GetStream(); + } + } + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSSocket"/> class. + /// </summary> + /// <param name="host">The host, where the socket should connect to.</param> + /// <param name="port">The port.</param> + /// <param name="certificatePath">The certificate path.</param> + /// <param name="certValidator">User defined cert validator.</param> + /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param> + /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param> + public TTLSSocket( + string host, + int port, + string certificatePath, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls) + : this(host, port, 0, X509Certificate.CreateFromCertFile(certificatePath), certValidator, localCertificateSelectionCallback, sslProtocols) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSSocket"/> class. + /// </summary> + /// <param name="host">The host, where the socket should connect to.</param> + /// <param name="port">The port.</param> + /// <param name="certificate">The certificate.</param> + /// <param name="certValidator">User defined cert validator.</param> + /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param> + /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param> + public TTLSSocket( + string host, + int port, + X509Certificate certificate = null, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls) + : this(host, port, 0, certificate, certValidator, localCertificateSelectionCallback, sslProtocols) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="TTLSSocket"/> class. + /// </summary> + /// <param name="host">The host, where the socket should connect to.</param> + /// <param name="port">The port.</param> + /// <param name="timeout">The timeout.</param> + /// <param name="certificate">The certificate.</param> + /// <param name="certValidator">User defined cert validator.</param> + /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param> + /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param> + public TTLSSocket( + string host, + int port, + int timeout, + X509Certificate certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls) + { + this.host = host; + this.port = port; + this.timeout = timeout; + this.certificate = certificate; + this.certValidator = certValidator; + this.localCertificateSelectionCallback = localCertificateSelectionCallback; + this.sslProtocols = sslProtocols; + + InitSocket(); + } + + /// <summary> + /// Creates the TcpClient and sets the timeouts + /// </summary> + private void InitSocket() + { + client = TSocketVersionizer.CreateTcpClient(); + client.ReceiveTimeout = client.SendTimeout = timeout; + client.Client.NoDelay = true; + } + + /// <summary> + /// Sets Send / Recv Timeout for IO + /// </summary> + public int Timeout + { + set + { + this.client.ReceiveTimeout = this.client.SendTimeout = this.timeout = value; + } + } + + /// <summary> + /// Gets the TCP client. + /// </summary> + public TcpClient TcpClient + { + get + { + return client; + } + } + + /// <summary> + /// Gets the host. + /// </summary> + public string Host + { + get + { + return host; + } + } + + /// <summary> + /// Gets the port. + /// </summary> + public int Port + { + get + { + return port; + } + } + + /// <summary> + /// Gets a value indicating whether TCP Client is Cpen + /// </summary> + public override bool IsOpen + { + get + { + if (this.client == null) + { + return false; + } + + return this.client.Connected; + } + } + + /// <summary> + /// Validates the certificates!<br/> + /// </summary> + /// <param name="sender">The sender-object.</param> + /// <param name="certificate">The used certificate.</param> + /// <param name="chain">The certificate chain.</param> + /// <param name="sslValidationErrors">An enum, which lists all the errors from the .NET certificate check.</param> + /// <returns></returns> + private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors) + { + return (sslValidationErrors == SslPolicyErrors.None); + } + + /// <summary> + /// Connects to the host and starts the routine, which sets up the TLS + /// </summary> + public override void Open() + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (string.IsNullOrEmpty(host)) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (client == null) + { + InitSocket(); + } + + if (timeout == 0) // no timeout -> infinite + { + client.Connect(host, port); + } + else // we have a timeout -> use it + { + ConnectHelper hlp = new ConnectHelper(client); + IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); + bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; + if (!bConnected) + { + lock (hlp.Mutex) + { + if (hlp.CallbackDone) + { + asyncres.AsyncWaitHandle.Close(); + client.Close(); + } + else + { + hlp.DoCleanup = true; + client = null; + } + } + throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); + } + } + + setupTLS(); + } + + /// <summary> + /// Creates a TLS-stream and lays it over the existing socket + /// </summary> + public void setupTLS() + { + RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator; + + if (this.localCertificateSelectionCallback != null) + { + this.secureStream = new SslStream( + this.client.GetStream(), + false, + validator, + this.localCertificateSelectionCallback + ); + } + else + { + this.secureStream = new SslStream( + this.client.GetStream(), + false, + validator + ); + } + + try + { + if (isServer) + { + // Server authentication + this.secureStream.AuthenticateAsServer(this.certificate, this.certValidator != null, sslProtocols, true); + } + else + { + // Client authentication + X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection(); + this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true); + } + } + catch (Exception) + { + this.Close(); + throw; + } + + inputStream = this.secureStream; + outputStream = this.secureStream; + } + + static void ConnectCallback(IAsyncResult asyncres) + { + ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; + lock (hlp.Mutex) + { + hlp.CallbackDone = true; + + try + { + if (hlp.Client.Client != null) + hlp.Client.EndConnect(asyncres); + } + catch (Exception) + { + // catch that away + } + + if (hlp.DoCleanup) + { + try + { + asyncres.AsyncWaitHandle.Close(); + } + catch (Exception) { } + + try + { + if (hlp.Client is IDisposable) + ((IDisposable)hlp.Client).Dispose(); + } + catch (Exception) { } + hlp.Client = null; + } + } + } + + private class ConnectHelper + { + public object Mutex = new object(); + public bool DoCleanup = false; + public bool CallbackDone = false; + public TcpClient Client; + public ConnectHelper(TcpClient client) + { + Client = client; + } + } + + /// <summary> + /// Closes the SSL Socket + /// </summary> + public override void Close() + { + base.Close(); + if (this.client != null) + { + this.client.Close(); + this.client = null; + } + + if (this.secureStream != null) + { + this.secureStream.Close(); + this.secureStream = null; + } + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransport.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransport.cs new file mode 100644 index 000000000..5e4ac22ea --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransport.cs @@ -0,0 +1,146 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.IO; + +namespace Thrift.Transport +{ + public abstract class TTransport : IDisposable + { + public abstract bool IsOpen + { + get; + } + + private byte[] _peekBuffer = new byte[1]; + private bool _hasPeekByte; + + public bool Peek() + { + //If we already have a byte read but not consumed, do nothing. + if (_hasPeekByte) + return true; + + //If transport closed we can't peek. + if (!IsOpen) + return false; + + //Try to read one byte. If succeeds we will need to store it for the next read. + try + { + int bytes = Read(_peekBuffer, 0, 1); + if (bytes == 0) + return false; + } + catch (IOException) + { + return false; + } + + _hasPeekByte = true; + return true; + } + + public abstract void Open(); + + public abstract void Close(); + + protected static void ValidateBufferArgs(byte[] buf, int off, int len) + { + if (buf == null) + throw new ArgumentNullException("buf"); + if (off < 0) + throw new ArgumentOutOfRangeException("Buffer offset is smaller than zero."); + if (len < 0) + throw new ArgumentOutOfRangeException("Buffer length is smaller than zero."); + if (off + len > buf.Length) + throw new ArgumentOutOfRangeException("Not enough data."); + } + + public abstract int Read(byte[] buf, int off, int len); + + public int ReadAll(byte[] buf, int off, int len) + { + ValidateBufferArgs(buf, off, len); + int got = 0; + + //If we previously peeked a byte, we need to use that first. + if (_hasPeekByte) + { + buf[off + got++] = _peekBuffer[0]; + _hasPeekByte = false; + } + + while (got < len) + { + int ret = Read(buf, off + got, len - got); + if (ret <= 0) + { + throw new TTransportException( + TTransportException.ExceptionType.EndOfFile, + "Cannot read, Remote side has closed"); + } + got += ret; + } + return got; + } + + public virtual void Write(byte[] buf) + { + Write(buf, 0, buf.Length); + } + + public abstract void Write(byte[] buf, int off, int len); + + public virtual void Flush() + { + } + + public virtual IAsyncResult BeginFlush(AsyncCallback callback, object state) + { + throw new TTransportException( + TTransportException.ExceptionType.Unknown, + "Asynchronous operations are not supported by this transport."); + } + + public virtual void EndFlush(IAsyncResult asyncResult) + { + throw new TTransportException( + TTransportException.ExceptionType.Unknown, + "Asynchronous operations are not supported by this transport."); + } + + #region " IDisposable Support " + // IDisposable + protected abstract void Dispose(bool disposing); + + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportException.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportException.cs new file mode 100644 index 000000000..7f6cc1889 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportException.cs @@ -0,0 +1,69 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Transport +{ + public class TTransportException : TException + { + protected ExceptionType type; + + public TTransportException() + : base() + { + } + + public TTransportException(ExceptionType type) + : this() + { + this.type = type; + } + + public TTransportException(ExceptionType type, string message, Exception inner = null) + : base(message, inner) + { + this.type = type; + } + + public TTransportException(string message, Exception inner = null) + : base(message, inner) + { + } + + public ExceptionType Type + { + get { return type; } + } + + public enum ExceptionType + { + Unknown, + NotOpen, + AlreadyOpen, + TimedOut, + EndOfFile, + Interrupted + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportFactory.cs b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportFactory.cs new file mode 100644 index 000000000..47a0c6265 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/Transport/TTransportFactory.cs @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; + +namespace Thrift.Transport +{ + /// <summary> + /// From Mark Slee & Aditya Agarwal of Facebook: + /// Factory class used to create wrapped instance of Transports. + /// This is used primarily in servers, which get Transports from + /// a ServerTransport and then may want to mutate them (i.e. create + /// a BufferedTransport from the underlying base transport) + /// </summary> + public class TTransportFactory + { + public virtual TTransport GetTransport(TTransport trans) + { + return trans; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/src/thrift.snk b/src/jaegertracing/thrift/lib/csharp/src/thrift.snk Binary files differnew file mode 100644 index 000000000..97bc5812b --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/src/thrift.snk diff --git a/src/jaegertracing/thrift/lib/csharp/test/JSON/JSONTest.csproj b/src/jaegertracing/thrift/lib/csharp/test/JSON/JSONTest.csproj new file mode 100644 index 000000000..f07d43eec --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/JSON/JSONTest.csproj @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">x86</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{E37A0034-DCBF-4886-A0DA-25A03D12D975}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>JSONTest</RootNamespace> + <AssemblyName>JSONTest</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <TargetFrameworkProfile> + </TargetFrameworkProfile> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> + <PlatformTarget>x86</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="app.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\src\Thrift.csproj"> + <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/test/JSON/Program.cs b/src/jaegertracing/thrift/lib/csharp/test/JSON/Program.cs new file mode 100644 index 000000000..f61388ae7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/JSON/Program.cs @@ -0,0 +1,95 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using Thrift.Protocol; +using Thrift.Transport; + +namespace JSONTest +{ + class Program + { + static void Main(string[] args) + { + TestThrift2365(); // JSON binary decodes too much data + TestThrift2336(); // hex encoding using \uXXXX where 0xXXXX > 0xFF + TestThrift3403(); // JSON escaped unicode surrogate pair support. + } + + + public static void TestThrift2365() + { + var rnd = new Random(); + for (var len = 0; len < 10; ++len) + { + byte[] dataWritten = new byte[len]; + rnd.NextBytes(dataWritten); + + Stream stm = new MemoryStream(); + TTransport trans = new TStreamTransport(null, stm); + TProtocol prot = new TJSONProtocol(trans); + prot.WriteBinary(dataWritten); + + stm.Position = 0; + trans = new TStreamTransport(stm, null); + prot = new TJSONProtocol(trans); + byte[] dataRead = prot.ReadBinary(); + + Debug.Assert(dataRead.Length == dataWritten.Length); + for (var i = 0; i < dataRead.Length; ++i) + Debug.Assert(dataRead[i] == dataWritten[i]); + } + } + + + public static void TestThrift2336() + { + const string RUSSIAN_TEXT = "\u0420\u0443\u0441\u0441\u043a\u043e\u0435 \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"; + const string RUSSIAN_JSON = "\"\\u0420\\u0443\\u0441\\u0441\\u043a\\u043e\\u0435 \\u041d\\u0430\\u0437\\u0432\\u0430\\u043d\\u0438\\u0435\""; + + // prepare buffer with JSON data + byte[] rawBytes = new byte[RUSSIAN_JSON.Length]; + for (var i = 0; i < RUSSIAN_JSON.Length; ++i) + rawBytes[i] = (byte)(RUSSIAN_JSON[i] & (char)0xFF); // only low bytes + + // parse and check + var stm = new MemoryStream(rawBytes); + var trans = new TStreamTransport(stm, null); + var prot = new TJSONProtocol(trans); + Debug.Assert(prot.ReadString() == RUSSIAN_TEXT, "reading JSON with hex-encoded chars > 8 bit"); + } + + public static void TestThrift3403() + { + string GCLEF_TEXT = "\ud834\udd1e"; + const string GCLEF_JSON = "\"\\ud834\\udd1e\""; + + // parse and check + var stm = new MemoryStream(Encoding.UTF8.GetBytes(GCLEF_JSON)); + var trans = new TStreamTransport(stm, null); + var prot = new TJSONProtocol(trans); + Debug.Assert(prot.ReadString() == GCLEF_TEXT, "reading JSON with surrogate pair hex-encoded chars"); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/test/JSON/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fdff4a1a5 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/JSON/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +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("JSONTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[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("2b2e7d56-3e65-4368-92d7-e34d56b7105e")] + +// 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/jaegertracing/thrift/lib/csharp/test/JSON/app.config b/src/jaegertracing/thrift/lib/csharp/test/JSON/app.config new file mode 100644 index 000000000..9c1919d4f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/JSON/app.config @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<configuration> +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs new file mode 100644 index 000000000..c810a0891 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using Thrift.Collections; +using Thrift.Transport; +using Thrift.Protocol; +using Thrift.Server; +using Thrift; +using Test.Multiplex; + +namespace Test.Multiplex.Client +{ + public class TestClient + { + static void Execute(int port) + { + try + { + TTransport trans; + trans = new TSocket("localhost", port); + trans = new TFramedTransport(trans); + trans.Open(); + + TProtocol Protocol = new TBinaryProtocol(trans, true, true); + + TMultiplexedProtocol multiplex; + + multiplex = new TMultiplexedProtocol(Protocol, Constants.NAME_BENCHMARKSERVICE); + BenchmarkService.Iface bench = new BenchmarkService.Client(multiplex); + + multiplex = new TMultiplexedProtocol(Protocol, Constants.NAME_AGGR); + Aggr.Iface aggr = new Aggr.Client(multiplex); + + for (sbyte i = 1; 10 >= i; ++i) + { + aggr.addValue(bench.fibonacci(i)); + } + + foreach (int k in aggr.getValues()) + { + Console.Write(k.ToString() + " "); + Console.WriteLine(""); + } + trans.Close(); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + static void Main(string[] args) + { + int port = 9090; + if (args.Length > 0) + { + port = ushort.Parse(args[0]); + } + Execute(port); + Console.WriteLine("done."); + } + } +} + diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj new file mode 100644 index 000000000..09d20f503 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{5E91DA17-E548-415F-8C9F-9E84EDF8EE06}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MultiplexClient</RootNamespace> + <AssemblyName>MultiplexClient</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <IsWebBootstrapper>false</IsWebBootstrapper> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>0.13.0.0</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Multiplex.Test.Common.cs"> + <Link>Multiplex.Test.Common.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Aggr.cs" /> + <Compile Include="..\gen-csharp\BenchmarkService.cs" /> + <Compile Include="..\gen-csharp\Error.cs" /> + <Compile Include="Multiplex.Test.Client.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.2.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 2.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\src\Thrift.csproj"> + <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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> + --> + <PropertyGroup> + <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp" +del /f /q "$(ProjectDir)ThriftImpl.dll" +SET OUTPUT_DIR=$(ProjectDir) + +SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 + +SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 + +</PreBuildEvent> + </PropertyGroup> +</Project> diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0b65c1e52 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MultiplexClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("66FC61E5-420B-4b56-8012-D6D6CE22537F")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Makefile.am b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Makefile.am new file mode 100644 index 000000000..9c1f1b8b7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Makefile.am @@ -0,0 +1,63 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +GENERATED = \ + gen-csharp/Aggr.cs \ + gen-csharp/BenchmarkService.cs \ + gen-csharp/Error.cs + +BUILT_SOURCES = $(GENERATED) + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +gen-csharp/Aggr.cs: $(top_srcdir)/contrib/async-test/aggr.thrift + $(THRIFT) --gen csharp $< + +gen-csharp/BenchmarkService.cs gen-csharp/Error.cs: $(top_srcdir)/lib/rb/benchmark/Benchmark.thrift + $(THRIFT) --gen csharp $< + +ThriftImpl.dll: Multiplex.Test.Common.cs $(GENERATED) ../../Thrift.dll + $(CSC) $(CSC_DEFINES) -t:library -out:./ThriftImpl.dll -reference:../../Thrift.dll $(GENERATED) $< + +MultiplexClient.exe: Client/Multiplex.Test.Client.cs ThriftImpl.dll + $(CSC) $(CSC_DEFINES) -out:$@ -reference:../../Thrift.dll -reference:ThriftImpl.dll $< + +MultiplexServer.exe: Server/Multiplex.Test.Server.cs ThriftImpl.dll + $(CSC) $(CSC_DEFINES) -out:$@ -reference:../../Thrift.dll -reference:ThriftImpl.dll $< + +CLEANFILES = \ + MultiplexClient.exe \ + MultiplexServer.exe \ + ThriftImpl.dll + +DISTCLEANFILES = \ + Makefile.in + +clean-local: + $(RM) -rf gen-csharp + +dist-hook: + $(RM) -r $(distdir)/gen-csharp/ + +TESTPORT = 9501 +check-local: MultiplexServer.exe MultiplexClient.exe + echo $(TESTPORT) + MONO_PATH=../../ timeout 10 mono MultiplexServer.exe $(TESTPORT) & + sleep 1 + MONO_PATH=../../ mono MultiplexClient.exe $(TESTPORT) diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs new file mode 100644 index 000000000..a687852d9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ +using System; +using System.Collections.Generic; +using Thrift.Collections; +using Thrift.Transport; +using Thrift.Protocol; +using Thrift.Server; + +namespace Test.Multiplex +{ + public class Constants + { + public const string NAME_BENCHMARKSERVICE = "BenchmarkService"; + public const string NAME_AGGR = "Aggr"; + } +} + + diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs new file mode 100644 index 000000000..9786189bb --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using Thrift.Collections; +using Thrift.Transport; +using Thrift.Protocol; +using Thrift.Server; +using Thrift; +using Test.Multiplex; + +namespace Test.Multiplex.Server +{ + public class TestServer + { + class BenchmarkServiceImpl : BenchmarkService.Iface + { + public int fibonacci(sbyte n) + { + int prev, next, result; + prev = 0; + result = 1; + while (n > 0) + { + next = result + prev; + prev = result; + result = next; + --n; + } + return result; + } + } + + class AggrServiceImpl : Aggr.Iface + { + List<int> values = new List<int>(); + + public void addValue(int value) + { + values.Add(value); + } + + public List<int> getValues() + { + return values; + } + } + + static void Execute(int port) + { + try + { + // create protocol factory, default to BinaryProtocol + TProtocolFactory ProtocolFactory = new TBinaryProtocol.Factory(true,true); + TServerTransport servertrans = new TServerSocket(port, 0, false); + TTransportFactory TransportFactory = new TFramedTransport.Factory(); + + BenchmarkService.Iface benchHandler = new BenchmarkServiceImpl(); + TProcessor benchProcessor = new BenchmarkService.Processor(benchHandler); + + Aggr.Iface aggrHandler = new AggrServiceImpl(); + TProcessor aggrProcessor = new Aggr.Processor(aggrHandler); + + TMultiplexedProcessor multiplex = new TMultiplexedProcessor(); + multiplex.RegisterProcessor(Constants.NAME_BENCHMARKSERVICE, benchProcessor); + multiplex.RegisterProcessor(Constants.NAME_AGGR, aggrProcessor); + + TServer ServerEngine = new TSimpleServer(multiplex, servertrans, TransportFactory, ProtocolFactory); + + Console.WriteLine("Starting the server ..."); + ServerEngine.Serve(); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + static void Main(string[] args) + { + int port = 9090; + if (args.Length > 0) + { + port = ushort.Parse(args[0]); + } + Execute(port); + } + } +} + diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj new file mode 100644 index 000000000..23d325362 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{D592BDF3-0DCE-48FB-890F-E4AE1D9CE7CD}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MultiplexServer</RootNamespace> + <AssemblyName>MultiplexServer</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <IsWebBootstrapper>false</IsWebBootstrapper> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>0.13.0.0</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Multiplex.Test.Common.cs"> + <Link>Multiplex.Test.Common.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Aggr.cs" /> + <Compile Include="..\gen-csharp\BenchmarkService.cs" /> + <Compile Include="..\gen-csharp\Error.cs" /> + <Compile Include="Multiplex.Test.Server.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.2.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 2.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\src\Thrift.csproj"> + <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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> + --> + <PropertyGroup> + <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp" +del /f /q "$(ProjectDir)ThriftImpl.dll" +SET OUTPUT_DIR=$(ProjectDir) + +SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 + +SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 + +</PreBuildEvent> + </PropertyGroup> +</Project> diff --git a/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2b8a6af23 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MultiplexServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("F2F436C1-3D4F-411a-ADC3-B98848476A8E")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs new file mode 100644 index 000000000..855184fd2 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Web.Mvc; + +namespace ThriftMVCTest +{ + public static class FilterConfig + { + public static void RegisterGlobalFilters(GlobalFilterCollection filters) + { + filters.Add(new HandleErrorAttribute()); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs new file mode 100644 index 000000000..b4b6023d6 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Web.Mvc; +using System.Web.Routing; + +namespace ThriftMVCTest +{ + public static class RouteConfig + { + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.thrift"); + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs new file mode 100644 index 000000000..7f26184fa --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using Thrift.Transport; + +namespace ThriftMVCTest +{ + public class AsyncHttpHandler : THttpTaskAsyncHandler + { + public AsyncHttpHandler() + : base( + new Thrift.Test.SecondService.AsyncProcessor(new SecondServiceImpl())) + { + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs new file mode 100644 index 000000000..c9a1ec43f --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Threading.Tasks; +using System.Web.Mvc; +using Thrift.Protocol; +using Thrift.Test; +using Thrift.Transport; + +namespace ThriftMVCTest.Controllers +{ + public class HomeController : Controller + { + public ActionResult Index() + { + return View(); + } + + public async Task<ActionResult> TestThriftAsync() + { + var baseUri = new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, + Url.Content("~"))); + + SecondService.IAsync asyncService = + new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Async.thrift")))); + + var result = await asyncService.secondtestStringAsync("TestString"); + if (result != "testString(\"TestString\")") + { + throw new Exception("The wrong result was returned"); + } + + return RedirectToAction("Index"); + } + + public ActionResult TestThriftSync() + { + var baseUri = new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, + Url.Content("~"))); + + SecondService.ISync service = + new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Sync.thrift")))); + + var result = service.secondtestString("TestString"); + if (result != "testString(\"TestString\")") + { + throw new Exception("The wrong result was returned"); + } + + return RedirectToAction("Index"); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax new file mode 100644 index 000000000..7bb688c7a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax @@ -0,0 +1,19 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="ThriftMVCTest.MvcApplication" Language="C#" %> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax.cs new file mode 100644 index 000000000..59731efb3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Global.asax.cs @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Web.Mvc; +using System.Web.Routing; + +namespace ThriftMVCTest +{ + public class MvcApplication : System.Web.HttpApplication + { + protected void Application_Start() + { + AreaRegistration.RegisterAllAreas(); + FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); + RouteConfig.RegisterRoutes(RouteTable.Routes); + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b812aaf1d --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ThriftMVCTest")] +[assembly: AssemblyDescription("A web project for testing the thrift ASP.NET features.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("366f9bd0-3c0e-48aa-b2ca-61fd4a93e427")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs new file mode 100644 index 000000000..fad301a35 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Threading.Tasks; +using Thrift.Test; + +namespace ThriftMVCTest +{ + public class SecondServiceImpl : SecondService.IAsync, SecondService.ISync + { + public Task<string> secondtestStringAsync(string thing) + { + return Task.FromResult(thing); + } + + public string secondtestString(string thing) + { + return "testString(\"" + thing + "\")"; + } + } +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs new file mode 100644 index 000000000..4fe26624a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using Thrift.Transport; + +namespace ThriftMVCTest +{ + public class SyncHttpHandler : THttpHandler + { + public SyncHttpHandler() + : base( + new Thrift.Test.SecondService.Processor(new SecondServiceImpl())) + { + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj new file mode 100644 index 000000000..0eb969a04 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<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> + <ProductVersion> + </ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{891B4487-C7BA-427E-BBC8-4C596C229A10}</ProjectGuid> + <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ThriftMVCTest</RootNamespace> + <AssemblyName>ThriftMVCTest</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MvcBuildViews>false</MvcBuildViews> + <UseIISExpress>true</UseIISExpress> + <IISExpressSSLPort /> + <IISExpressAnonymousAuthentication /> + <IISExpressWindowsAuthentication /> + <IISExpressUseClassicPipelineMode /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Web.DynamicData" /> + <Reference Include="System.Web.Entity" /> + <Reference Include="System.Web.ApplicationServices" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Web" /> + <Reference Include="System.Web.Extensions" /> + <Reference Include="System.Web.Abstractions" /> + <Reference Include="System.Web.Routing" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Web.Services" /> + <Reference Include="System.EnterpriseServices" /> + <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http"> + </Reference> + <Reference Include="System.Net.Http.WebRequest"> + </Reference> + <Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath> + </Reference> + <Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath> + </Reference> + <Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath> + </Reference> + <Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath> + </Reference> + <Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath> + </Reference> + <Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <Private>True</Private> + <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath> + </Reference> + <Reference Include="ThriftImpl"> + <HintPath>.\ThriftImpl.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="App_Start\FilterConfig.cs" /> + <Compile Include="App_Start\RouteConfig.cs" /> + <Compile Include="SyncHttpHandler.cs" /> + <Compile Include="AsyncHttpHandler.cs" /> + <Compile Include="Controllers\HomeController.cs" /> + <Compile Include="Global.asax.cs"> + <DependentUpon>Global.asax</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SecondServiceImpl.cs" /> + </ItemGroup> + <ItemGroup> + <Content Include="favicon.ico" /> + <Content Include="Global.asax" /> + <Content Include="Web.config" /> + <Content Include="Web.Debug.config"> + <DependentUpon>Web.config</DependentUpon> + </Content> + <Content Include="Web.Release.config"> + <DependentUpon>Web.config</DependentUpon> + </Content> + <Content Include="Views\Web.config" /> + <Content Include="Views\_ViewStart.cshtml" /> + <Content Include="Views\Shared\_Layout.cshtml" /> + <Content Include="Views\Home\Index.cshtml" /> + </ItemGroup> + <ItemGroup> + <Folder Include="App_Data\" /> + </ItemGroup> + <ItemGroup> + <Content Include="packages.config"> + <SubType>Designer</SubType> + </Content> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\src\Thrift.45.csproj"> + <Project>{ebce35da-cf6a-42bc-a357-a9c09b534299}</Project> + <Name>Thrift.45</Name> + </ProjectReference> + </ItemGroup> + <PropertyGroup> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" /> + <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'"> + <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> + </Target> + <ProjectExtensions> + <VisualStudio> + <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> + <WebProjectProperties> + <UseIIS>True</UseIIS> + <AutoAssignPort>True</AutoAssignPort> + <DevelopmentServerPort>57482</DevelopmentServerPort> + <DevelopmentServerVPath>/</DevelopmentServerVPath> + <IISUrl>http://localhost:57482/</IISUrl> + <NTLMAuthentication>False</NTLMAuthentication> + <UseCustomServer>False</UseCustomServer> + <CustomServerUrl> + </CustomServerUrl> + <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> + </WebProjectProperties> + </FlavorProperties> + </VisualStudio> + </ProjectExtensions> + <PropertyGroup> + <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp" +del /f /q "$(ProjectDir)ThriftImpl.dll" +SET OUTPUT_DIR=$(ProjectDir) +SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\test\ThriftTest.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\..\..\compiler\cpp\Debug\thrift.exe" --gen csharp:async=true -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 +"$(MSBuildToolsPath)\Csc.exe" /t:library /out:"$(ProjectDir)ThriftImpl.dll" /recurse:"$(ProjectDir)gen-csharp"\* /reference:"$(ProjectDir)..\..\src\bin\Debug\Thrift45.dll"</PreBuildEvent> + </PropertyGroup> + <!-- 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>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml new file mode 100644 index 000000000..f0ca7da20 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml @@ -0,0 +1,25 @@ +@* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*@ + +@{ + ViewBag.Title = "Home Page"; +} + +<p>@Html.ActionLink("Test Thrift Async Service", "TestThriftAsync")</p> +<p>@Html.ActionLink("Test Thrift Sync Service", "TestThriftSync")</p> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml new file mode 100644 index 000000000..b41c99a10 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml @@ -0,0 +1,30 @@ +@* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*@ + +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Thrift ASP.NET Test</title> +</head> +<body> + @RenderBody() +</body> +</html> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Web.config b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Web.config new file mode 100644 index 000000000..3c211387a --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/Web.config @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<configuration> + <configSections> + <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> + <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> + </sectionGroup> + </configSections> + + <system.web.webPages.razor> + <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> + <pages pageBaseType="System.Web.Mvc.WebViewPage"> + <namespaces> + <add namespace="System.Web.Mvc" /> + <add namespace="System.Web.Mvc.Ajax" /> + <add namespace="System.Web.Mvc.Html" /> + <add namespace="System.Web.Optimization"/> + <add namespace="System.Web.Routing" /> + <add namespace="ThriftMVCTest" /> + </namespaces> + </pages> + </system.web.webPages.razor> + + <appSettings> + <add key="webpages:Enabled" value="false" /> + </appSettings> + + <system.webServer> + <handlers> + <remove name="BlockViewHandler"/> + <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> + </handlers> + </system.webServer> + + <system.web> + <compilation> + <assemblies> + <add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> + </assemblies> + </compilation> + </system.web> +</configuration> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml new file mode 100644 index 000000000..8cde2eeb9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml @@ -0,0 +1,22 @@ +@* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*@ + +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; +} diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Debug.config b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Debug.config new file mode 100644 index 000000000..45d56d809 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Debug.config @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> + <!-- + In the example below, the "SetAttributes" transform will change the value of + "connectionString" to use "ReleaseSQLServer" only when the "Match" locator + finds an attribute "name" that has a value of "MyDB". + + <connectionStrings> + <add name="MyDB" + connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" + xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> + </connectionStrings> + --> + <system.web> + <!-- + In the example below, the "Replace" transform will replace the entire + <customErrors> section of your Web.config file. + Note that because there is only one customErrors section under the + <system.web> node, there is no need to use the "xdt:Locator" attribute. + + <customErrors defaultRedirect="GenericError.htm" + mode="RemoteOnly" xdt:Transform="Replace"> + <error statusCode="500" redirect="InternalError.htm"/> + </customErrors> + --> + </system.web> +</configuration> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Release.config b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Release.config new file mode 100644 index 000000000..157c340ca --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.Release.config @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> + <!-- + In the example below, the "SetAttributes" transform will change the value of + "connectionString" to use "ReleaseSQLServer" only when the "Match" locator + finds an attribute "name" that has a value of "MyDB". + + <connectionStrings> + <add name="MyDB" + connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" + xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> + </connectionStrings> + --> + <system.web> + <compilation xdt:Transform="RemoveAttributes(debug)" /> + <!-- + In the example below, the "Replace" transform will replace the entire + <customErrors> section of your Web.config file. + Note that because there is only one customErrors section under the + <system.web> node, there is no need to use the "xdt:Locator" attribute. + + <customErrors defaultRedirect="GenericError.htm" + mode="RemoteOnly" xdt:Transform="Replace"> + <error statusCode="500" redirect="InternalError.htm"/> + </customErrors> + --> + </system.web> +</configuration> diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.config b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.config new file mode 100644 index 000000000..9c57d117c --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/Web.config @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<!-- + For more information on how to configure your ASP.NET application, please visit + http://go.microsoft.com/fwlink/?LinkId=301880 + --> +<configuration> + <appSettings> + <add key="webpages:Version" value="3.0.0.0" /> + <add key="webpages:Enabled" value="false" /> + <add key="ClientValidationEnabled" value="true" /> + <add key="UnobtrusiveJavaScriptEnabled" value="true" /> + <add key="owin:AutomaticAppStartup" value="false" /> + </appSettings> + <system.web> + <authentication mode="None" /> + <compilation debug="true" targetFramework="4.5" /> + <httpRuntime targetFramework="4.5" /> + </system.web> + <system.webServer> + <modules> + <remove name="FormsAuthentication" /> + </modules> + <handlers> + <add name="AsyncHttpHandler" verb="*" path="Async.thrift" type="ThriftMVCTest.AsyncHttpHandler, ThriftMVCTest" /> + <add name="SyncHttpHandler" verb="*" path="Sync.thrift" type="ThriftMVCTest.SyncHttpHandler, ThriftMVCTest" /> + </handlers> + </system.webServer> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" /> + <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> + <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/favicon.ico b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/favicon.ico Binary files differnew file mode 100644 index 000000000..a3a799985 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/favicon.ico diff --git a/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/packages.config b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/packages.config new file mode 100644 index 000000000..98c8416f5 --- /dev/null +++ b/src/jaegertracing/thrift/lib/csharp/test/ThriftMVCTest/packages.config @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<packages> + <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" /> + <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" /> + <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" /> + <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" /> +</packages>
\ No newline at end of file |