Browse Source

1.指挥员(长)指挥能力考评系统

2.消防救援单位信息考核系统
3.中高级指挥长考评系统
master
杨栋梁 11 months ago
parent
commit
214b565ef9
  1. 144
      .gitignore
  2. 8
      Assets/JsonDotNet.meta
  3. 8
      Assets/JsonDotNet/Assemblies.meta
  4. 8
      Assets/JsonDotNet/Assemblies/AOT.meta
  5. BIN
      Assets/JsonDotNet/Assemblies/AOT/Newtonsoft.Json.dll
  6. 76
      Assets/JsonDotNet/Assemblies/AOT/Newtonsoft.Json.dll.meta
  7. 8
      Assets/JsonDotNet/Assemblies/Standalone.meta
  8. BIN
      Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
  9. 75
      Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll.meta
  10. 8
      Assets/JsonDotNet/Assemblies/Windows.meta
  11. BIN
      Assets/JsonDotNet/Assemblies/Windows/Newtonsoft.Json.dll
  12. 67
      Assets/JsonDotNet/Assemblies/Windows/Newtonsoft.Json.dll.meta
  13. 8
      Assets/Plugins.meta
  14. 8
      Assets/Plugins/Best HTTP.meta
  15. 8
      Assets/Plugins/Best HTTP/Examples.meta
  16. 8
      Assets/Plugins/Best HTTP/Examples/HTTP.meta
  17. 209
      Assets/Plugins/Best HTTP/Examples/HTTP/AssetBundleSample.cs
  18. 10
      Assets/Plugins/Best HTTP/Examples/HTTP/AssetBundleSample.cs.meta
  19. 197
      Assets/Plugins/Best HTTP/Examples/HTTP/MultipartFormDataStream.cs
  20. 13
      Assets/Plugins/Best HTTP/Examples/HTTP/MultipartFormDataStream.cs.meta
  21. 96
      Assets/Plugins/Best HTTP/Examples/HTTP/ResumableStreamingSample.cs
  22. 10
      Assets/Plugins/Best HTTP/Examples/HTTP/ResumableStreamingSample.cs.meta
  23. 272
      Assets/Plugins/Best HTTP/Examples/HTTP/StreamingSample.cs
  24. 11
      Assets/Plugins/Best HTTP/Examples/HTTP/StreamingSample.cs.meta
  25. 159
      Assets/Plugins/Best HTTP/Examples/HTTP/TextureDownloadSample.cs
  26. 10
      Assets/Plugins/Best HTTP/Examples/HTTP/TextureDownloadSample.cs.meta
  27. 222
      Assets/Plugins/Best HTTP/Examples/HTTP/UploadStream.cs
  28. 10
      Assets/Plugins/Best HTTP/Examples/HTTP/UploadStream.cs.meta
  29. 8
      Assets/Plugins/Best HTTP/Examples/Helpers.meta
  30. 8
      Assets/Plugins/Best HTTP/Examples/Helpers/Components.meta
  31. 57
      Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cache.cs
  32. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cache.cs.meta
  33. 63
      Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cookies.cs
  34. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cookies.cs.meta
  35. 60
      Assets/Plugins/Best HTTP/Examples/Helpers/GUIHelper.cs
  36. 10
      Assets/Plugins/Best HTTP/Examples/Helpers/GUIHelper.cs.meta
  37. 36
      Assets/Plugins/Best HTTP/Examples/Helpers/Link.cs
  38. 13
      Assets/Plugins/Best HTTP/Examples/Helpers/Link.cs.meta
  39. 23
      Assets/Plugins/Best HTTP/Examples/Helpers/SampleBase.cs
  40. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/SampleBase.cs.meta
  41. 8
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI.meta
  42. 22
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/Category.cs
  43. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/Category.cs.meta
  44. 37
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleInfo.cs
  45. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleInfo.cs.meta
  46. 32
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleListItem.cs
  47. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleListItem.cs.meta
  48. 101
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/SampleSelectorUI.cs
  49. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/SampleSelectorUI.cs.meta
  50. 26
      Assets/Plugins/Best HTTP/Examples/Helpers/TextListItem.cs
  51. 11
      Assets/Plugins/Best HTTP/Examples/Helpers/TextListItem.cs.meta
  52. 8
      Assets/Plugins/Best HTTP/Examples/Plugin.meta
  53. 57
      Assets/Plugins/Best HTTP/Examples/Plugin/AsyncExtensions.cs
  54. 11
      Assets/Plugins/Best HTTP/Examples/Plugin/AsyncExtensions.cs.meta
  55. 103
      Assets/Plugins/Best HTTP/Examples/SampleRoot.cs
  56. 13
      Assets/Plugins/Best HTTP/Examples/SampleRoot.cs.meta
  57. 8
      Assets/Plugins/Best HTTP/Examples/Server-Sent Events.meta
  58. 156
      Assets/Plugins/Best HTTP/Examples/Server-Sent Events/SimpleSample.cs
  59. 11
      Assets/Plugins/Best HTTP/Examples/Server-Sent Events/SimpleSample.cs.meta
  60. 8
      Assets/Plugins/Best HTTP/Examples/SignalR.meta
  61. 8
      Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers.meta
  62. 135
      Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleCookieAuthentication.cs
  63. 10
      Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleCookieAuthentication.cs.meta
  64. 97
      Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleHeaderAuthentication.cs
  65. 10
      Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleHeaderAuthentication.cs.meta
  66. 8
      Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders.meta
  67. 23
      Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/JSonDotnetEncoder.cs
  68. 10
      Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/JSonDotnetEncoder.cs.meta
  69. 28
      Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/LitJsonEncoder.cs
  70. 10
      Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/LitJsonEncoder.cs.meta
  71. 8
      Assets/Plugins/Best HTTP/Examples/SignalRCore.meta
  72. 240
      Assets/Plugins/Best HTTP/Examples/SignalRCore/AsyncTestHubSample.cs
  73. 13
      Assets/Plugins/Best HTTP/Examples/SignalRCore/AsyncTestHubSample.cs.meta
  74. 8
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers.meta
  75. 68
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers/HeaderAuthenticator.cs
  76. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers/HeaderAuthenticator.cs.meta
  77. 8
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders.meta
  78. 37
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/JsonDotNetEncoder.cs
  79. 13
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/JsonDotNetEncoder.cs.meta
  80. 47
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/LitJsonEncoder.cs
  81. 13
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/LitJsonEncoder.cs.meta
  82. 567
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackCSharpProtocol.cs
  83. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackCSharpProtocol.cs.meta
  84. 868
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackProtocol.cs
  85. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackProtocol.cs.meta
  86. 178
      Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithAuthorizationSample.cs
  87. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithAuthorizationSample.cs.meta
  88. 307
      Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithPreAuthorizationSample.cs
  89. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithPreAuthorizationSample.cs.meta
  90. 34
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Person.cs
  91. 13
      Assets/Plugins/Best HTTP/Examples/SignalRCore/Person.cs.meta
  92. 240
      Assets/Plugins/Best HTTP/Examples/SignalRCore/RedirectSample.cs
  93. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/RedirectSample.cs.meta
  94. 242
      Assets/Plugins/Best HTTP/Examples/SignalRCore/TestHubSample.cs
  95. 11
      Assets/Plugins/Best HTTP/Examples/SignalRCore/TestHubSample.cs.meta
  96. 404
      Assets/Plugins/Best HTTP/Examples/SignalRCore/UploadHubSample.cs
  97. 12
      Assets/Plugins/Best HTTP/Examples/SignalRCore/UploadHubSample.cs.meta
  98. 8
      Assets/Plugins/Best HTTP/Examples/SocketIO.meta
  99. 8
      Assets/Plugins/Best HTTP/Examples/SocketIO/SocketIO Json Encoders.meta
  100. 27
      Assets/Plugins/Best HTTP/Examples/SocketIO/SocketIO Json Encoders/JsonDotNetEncoder.cs
  101. Some files were not shown because too many files have changed in this diff Show More

144
.gitignore vendored

@ -0,0 +1,144 @@
# ---> Unity
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/Assets/StreamingAssets/AssetBundles/
/Assets/StreamingAssets/Systems/
# Autogenerated VS/MD solution and project files
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
# Unity3D generated meta files
# Unity3D Generated File On Crash Reports
sysinfo.txt
# ---> C Sharp
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
[Bb]in/
[Oo]bj/
# mstest test results
TestResults
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc
*.vssscc
.builds
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Publish Web Output
*.Publish.xml
# NuGet Packages Directory
packages
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
[Bb]in
[Oo]bj
sql
TestResults
[Tt]est[Rr]esult*
*.Cache
ClientBin
[Ss]tyle[Cc]op.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
/Logs
/.vs
/Assets/StreamingAssets/AssetBundles.meta
/Assets/StreamingAssets/ScenePics
.vsconfig
UserSettings
/UserSettings
UserSettings
/UserSettings/EditorUserSettings.asset
/Assets/Plugins/tripolygon/PastelTown-BuiltInRP-UModeler/Textures/debug.log.meta
/Assets/StreamingAssets/model
/Assets/StreamingAssets/model.meta

8
Assets/JsonDotNet.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f106eb2547e82e34a992bd3612baf073
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/JsonDotNet/Assemblies.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57597f74dcc2b134d8b4affb37eb371a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/JsonDotNet/Assemblies/AOT.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1ce3e085b670ef7408bf0db1d6ad9437
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JsonDotNet/Assemblies/AOT/Newtonsoft.Json.dll

Binary file not shown.

76
Assets/JsonDotNet/Assemblies/AOT/Newtonsoft.Json.dll.meta

@ -0,0 +1,76 @@
fileFormatVersion: 2
guid: 6a3c684705042f345975d924f6983e36
timeCreated: 1466788352
licenseType: Store
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Android:
enabled: 1
settings:
CPU: AnyCPU
Any:
enabled: 0
settings: {}
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
enabled: 0
settings:
CPU: x86
Linux64:
enabled: 0
settings:
CPU: x86_64
OSXIntel:
enabled: 0
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 0
settings:
CPU: AnyCPU
SamsungTV:
enabled: 1
settings:
STV_MODEL: STANDARD_13
Tizen:
enabled: 1
settings: {}
WebGL:
enabled: 1
settings: {}
Win:
enabled: 0
settings:
CPU: AnyCPU
Win64:
enabled: 0
settings:
CPU: AnyCPU
WindowsStoreApps:
enabled: 1
settings:
CPU: AnyCPU
DontProcess: False
PlaceholderPath: Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
SDK: AnySDK
ScriptingBackend: Il2Cpp
iOS:
enabled: 1
settings:
CompileFlags:
FrameworkDependencies:
tvOS:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/JsonDotNet/Assemblies/Standalone.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 17f5d20e192afae459aa673c7d64a7b6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll

Binary file not shown.

75
Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll.meta

@ -0,0 +1,75 @@
fileFormatVersion: 2
guid: 17aef65a15b471f468b5fbeb4ff0c6a1
timeCreated: 1466788349
licenseType: Store
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Android:
enabled: 0
settings:
CPU: AnyCPU
Any:
enabled: 0
settings: {}
Editor:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
enabled: 1
settings:
CPU: x86
Linux64:
enabled: 1
settings:
CPU: x86_64
LinuxUniversal:
enabled: 1
settings:
CPU: AnyCPU
OSXIntel:
enabled: 1
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 1
settings:
CPU: AnyCPU
OSXUniversal:
enabled: 1
settings:
CPU: AnyCPU
SamsungTV:
enabled: 0
settings:
STV_MODEL: STANDARD_13
Win:
enabled: 1
settings:
CPU: AnyCPU
Win64:
enabled: 1
settings:
CPU: AnyCPU
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
DontProcess: False
PlaceholderPath:
SDK: AnySDK
ScriptingBackend: Il2Cpp
iOS:
enabled: 0
settings:
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

8
Assets/JsonDotNet/Assemblies/Windows.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b47e3c4b434c79946ad8624d894c7aee
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JsonDotNet/Assemblies/Windows/Newtonsoft.Json.dll

Binary file not shown.

67
Assets/JsonDotNet/Assemblies/Windows/Newtonsoft.Json.dll.meta

@ -0,0 +1,67 @@
fileFormatVersion: 2
guid: 9b6ba260dada0ea4a871a42011f8b87d
timeCreated: 1466788355
licenseType: Store
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Android:
enabled: 0
settings:
CPU: AnyCPU
Any:
enabled: 0
settings: {}
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
enabled: 0
settings:
CPU: x86
Linux64:
enabled: 0
settings:
CPU: x86_64
OSXIntel:
enabled: 0
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 0
settings:
CPU: AnyCPU
SamsungTV:
enabled: 0
settings:
STV_MODEL: STANDARD_13
Win:
enabled: 0
settings:
CPU: AnyCPU
Win64:
enabled: 0
settings:
CPU: AnyCPU
WindowsStoreApps:
enabled: 1
settings:
CPU: AnyCPU
DontProcess: False
PlaceholderPath: Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
SDK: AnySDK
ScriptingBackend: DotNet
iOS:
enabled: 0
settings:
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9b865acf4b76d314089bd3c5e07bec1d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1540279ecf377fe4fb07e4f0358f15c1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7afc95d5f9cc73d4e887a85e7ac1c9b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/HTTP.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fa3387f79caf3814e8ecb6bbdeb9c73e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

209
Assets/Plugins/Best HTTP/Examples/HTTP/AssetBundleSample.cs

@ -0,0 +1,209 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
namespace BestHTTP.Examples.HTTP
{
public sealed class AssetBundleSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[Tooltip("The url of the resource to download")]
[SerializeField]
private string _path = "/AssetBundles/WebGL/demobundle.assetbundle";
[SerializeField]
private string _assetnameInBundle = "9443182_orig";
[SerializeField]
private Text _statusText;
[SerializeField]
private RawImage _rawImage;
[SerializeField]
private Button _downloadButton;
#pragma warning restore
#region Private Fields
/// <summary>
/// Reference to the request to be able to call Abort on it.
/// </summary>
HTTPRequest request;
/// <summary>
/// The downloaded and cached AssetBundle
/// </summary>
AssetBundle cachedBundle;
#endregion
#region Unity Events
protected override void Start()
{
base.Start();
this._statusText.text = "Waiting for user interaction";
}
void OnDestroy()
{
if (this.request != null)
this.request.Abort();
this.request = null;
UnloadBundle();
}
/// <summary>
/// GUI button callback
/// </summary>
public void OnStartDownloadButton()
{
this._downloadButton.enabled = false;
UnloadBundle();
StartCoroutine(DownloadAssetBundle());
}
#endregion
#region Private Helper Functions
IEnumerator DownloadAssetBundle()
{
// Create and send our request
request = new HTTPRequest(new Uri(this.sampleSelector.BaseURL + this._path)).Send();
this._statusText.text = "Download started";
// Wait while it's finishes and add some fancy dots to display something while the user waits for it.
// A simple "yield return StartCoroutine(request);" would do the job too.
while (request.State < HTTPRequestStates.Finished)
{
yield return new WaitForSeconds(0.1f);
this._statusText.text += ".";
}
// Check the outcome of our request.
switch (request.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (request.Response.IsSuccess)
{
#if !BESTHTTP_DISABLE_CACHING
if (request.Response.IsFromCache)
this._statusText.text = "Loaded from local cache!";
else
this._statusText.text = "Downloaded!";
#else
this._statusText.text = "Downloaded!";
#endif
// Start creating the downloaded asset bundle
AssetBundleCreateRequest async =
#if UNITY_5_3_OR_NEWER
AssetBundle.LoadFromMemoryAsync(request.Response.Data);
#else
AssetBundle.CreateFromMemory(request.Response.Data);
#endif
// wait for it
yield return async;
BestHTTP.PlatformSupport.Memory.BufferPool.Release(request.Response.Data);
// And process the bundle
yield return StartCoroutine(ProcessAssetBundle(async.assetBundle));
}
else
{
this._statusText.text = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
request.Response.StatusCode,
request.Response.Message,
request.Response.DataAsText);
Debug.LogWarning(this._statusText.text);
}
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
this._statusText.text = "Request Finished with Error! " + (request.Exception != null ? (request.Exception.Message + "\n" + request.Exception.StackTrace) : "No Exception");
Debug.LogError(this._statusText.text);
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
this._statusText.text = "Request Aborted!";
Debug.LogWarning(this._statusText.text);
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
this._statusText.text = "Connection Timed Out!";
Debug.LogError(this._statusText.text);
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
this._statusText.text = "Processing the request Timed Out!";
Debug.LogError(this._statusText.text);
break;
}
this._downloadButton.enabled = true;
}
/// <summary>
/// In this function we can do whatever we want with the freshly downloaded bundle.
/// In this example we will cache it for later use, and we will load a texture from it.
/// </summary>
IEnumerator ProcessAssetBundle(AssetBundle bundle)
{
if (bundle == null)
yield break;
// Save the bundle for future use
cachedBundle = bundle;
// Start loading the asset from the bundle
var asyncAsset =
#if UNITY_5_1 || UNITY_5_2 || UNITY_5_3_OR_NEWER
cachedBundle.LoadAssetAsync(this._assetnameInBundle, typeof(Texture2D));
#else
cachedBundle.LoadAsync(this._assetnameInBundle, typeof(Texture2D));
#endif
// wait til load
yield return asyncAsset;
// get the texture
this._rawImage.texture = asyncAsset.asset as Texture2D;
}
void UnloadBundle()
{
this._rawImage.texture = null;
if (cachedBundle != null)
{
cachedBundle.Unload(true);
cachedBundle = null;
}
}
#endregion
}
}

10
Assets/Plugins/Best HTTP/Examples/HTTP/AssetBundleSample.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 03eab9c6191c5cd4c9613084e817bd29
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

197
Assets/Plugins/Best HTTP/Examples/HTTP/MultipartFormDataStream.cs

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.IO;
using BestHTTP.Extensions;
using BestHTTP.PlatformSupport.Memory;
namespace BestHTTP
{
/// <summary>
/// Stream based implementation of the multipart/form-data Content-Type. Using this class reading a whole file into memory can be avoided.
/// This implementation expects that all streams has a final, accessible Length.
/// </summary>
public sealed class MultipartFormDataStream : System.IO.Stream
{
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return false; } }
public override long Length
{
get
{
// multipart/form-data requires a leading boundary that we can add when all streams are added.
// This final preparation could be user initiated, but we can do it automatically too when the HTTPRequest
// first access the Length property.
if (!this.prepared)
{
this.prepared = true;
this.Prepare();
}
return this._length;
}
}
private long _length;
public override long Position { get; set; }
/// <summary>
/// A random boundary generated in the constructor.
/// </summary>
private string boundary;
private Queue<StreamList> fields = new Queue<StreamList>(1);
private StreamList currentField;
private bool prepared;
public MultipartFormDataStream(HTTPRequest request)
{
this.boundary = "BestHTTP_MultipartFormDataStream_" + this.GetHashCode().ToString("X2");
request.SetHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
request.UploadStream = this;
request.UseUploadStreamLength = true;
}
public void AddField(string fieldName, string value)
{
AddField(fieldName, value, System.Text.Encoding.UTF8);
}
public void AddField(string fieldName, string value, System.Text.Encoding encoding)
{
var enc = encoding ?? System.Text.Encoding.UTF8;
var byteCount = enc.GetByteCount(value);
var buffer = BufferPool.Get(byteCount, true);
var stream = new BufferPoolMemoryStream();
enc.GetBytes(value, 0, value.Length, buffer, 0);
stream.Write(buffer, 0, byteCount);
stream.Position = 0;
string mime = encoding != null ? "text/plain; charset=" + encoding.WebName : null;
AddStreamField(stream, fieldName, null, mime);
}
public void AddStreamField(System.IO.Stream stream, string fieldName)
{
AddStreamField(stream, fieldName, null, null);
}
public void AddStreamField(System.IO.Stream stream, string fieldName, string fileName)
{
AddStreamField(stream, fieldName, fileName, null);
}
public void AddStreamField(System.IO.Stream stream, string fieldName, string fileName, string mimeType)
{
var header = new BufferPoolMemoryStream();
header.WriteLine("--" + this.boundary);
header.WriteLine("Content-Disposition: form-data; name=\"" + fieldName + "\"" + (!string.IsNullOrEmpty(fileName) ? "; filename=\"" + fileName + "\"" : string.Empty));
// Set up Content-Type head for the form.
if (!string.IsNullOrEmpty(mimeType))
header.WriteLine("Content-Type: " + mimeType);
//header.WriteLine("Content-Length: " + stream.Length.ToString());
header.WriteLine();
header.Position = 0;
var footer = new BufferPoolMemoryStream();
footer.Write(HTTPRequest.EOL, 0, HTTPRequest.EOL.Length);
footer.Position = 0;
// all wrapped streams going to be disposed by the StreamList wrapper.
var wrapper = new StreamList(header, stream, footer);
try
{
if (this._length >= 0)
this._length += wrapper.Length;
}
catch
{
this._length = -1;
}
this.fields.Enqueue(wrapper);
}
/// <summary>
/// Adds the final boundary.
/// </summary>
private void Prepare()
{
var boundaryStream = new BufferPoolMemoryStream();
boundaryStream.WriteLine("--" + this.boundary + "--");
boundaryStream.Position = 0;
this.fields.Enqueue(new StreamList(boundaryStream));
if (this._length >= 0)
this._length += boundaryStream.Length;
}
public override int Read(byte[] buffer, int offset, int length)
{
if (this.currentField == null && this.fields.Count == 0)
return -1;
if (this.currentField == null && this.fields.Count > 0)
this.currentField = this.fields.Dequeue();
int readCount = 0;
do
{
// read from the current stream
int count = this.currentField.Read(buffer, offset + readCount, length - readCount);
if (count > 0)
readCount += count;
else
{
// if the current field's stream is empty, go for the next one.
// dispose the current one first
try
{
this.currentField.Dispose();
}
catch
{ }
// no more fields/streams? exit
if (this.fields.Count == 0)
break;
// grab the next one
this.currentField = this.fields.Dequeue();
}
// exit when we reach the length goal, or there's no more streams to read from
} while (readCount < length && this.fields.Count > 0);
return readCount;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override void Flush() { }
}
}

13
Assets/Plugins/Best HTTP/Examples/HTTP/MultipartFormDataStream.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d54866f088b8c154db3325a2771b58af
timeCreated: 1582886645
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

96
Assets/Plugins/Best HTTP/Examples/HTTP/ResumableStreamingSample.cs

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
namespace BestHTTP.Examples.HTTP
{
public sealed class ResumableStreamingSample : StreamingSample
{
const string ProcessedBytesKey = "ProcessedBytes";
const string DownloadLengthKey = "DownloadLength";
/// <summary>
/// Expected content length
/// </summary>
protected override long DownloadLength { get { return PlayerPrefs.GetInt(this._downloadPath + DownloadLengthKey); } set { PlayerPrefs.SetInt(this._downloadPath + DownloadLengthKey, (int)value); } }
/// <summary>
/// Total processed bytes
/// </summary>
protected override long ProcessedBytes { get { return PlayerPrefs.GetInt(this._downloadPath + ProcessedBytesKey, 0); } set { PlayerPrefs.SetInt(this._downloadPath + ProcessedBytesKey, (int)value); } }
private long downloadStartedAt = 0;
protected override void Start()
{
base.Start();
// If we have a non-finished download, set the progress to the value where we left it
float progress = GetSavedProgress();
if (progress > 0.0f)
{
this._downloadProgressSlider.value = progress;
base._statusText.text = progress.ToString("F2");
}
}
protected override void SetupRequest()
{
base.SetupRequest();
// Are there any progress, that we can continue?
this.downloadStartedAt = this.ProcessedBytes;
if (this.downloadStartedAt > 0)
{
// Set the range header
request.SetRangeHeader(this.downloadStartedAt);
}
else
// This is a new request
DeleteKeys();
}
protected override void OnRequestFinished(HTTPRequest req, HTTPResponse resp)
{
base.OnRequestFinished(req, resp);
if (req.State == HTTPRequestStates.Finished && resp.IsSuccess)
DeleteKeys();
}
protected override void OnDownloadProgress(HTTPRequest originalRequest, long downloaded, long downloadLength)
{
double downloadPercent = ((this.downloadStartedAt + downloaded) / (double)this.DownloadLength) * 100;
this._downloadProgressSlider.value = (float)downloadPercent;
this._downloadProgressText.text = string.Format("{0:F1}%", downloadPercent);
}
protected override void ResetProcessedValues()
{
SetDataProcessedUI(this.ProcessedBytes, this.DownloadLength);
}
private float GetSavedProgress()
{
long down = this.ProcessedBytes;
long length = this.DownloadLength;
if (down > 0 && length > 0)
return (down / (float)length) * 100f;
return -1;
}
private void DeleteKeys()
{
PlayerPrefs.DeleteKey(this._downloadPath + ProcessedBytesKey);
PlayerPrefs.DeleteKey(this._downloadPath + DownloadLengthKey);
PlayerPrefs.Save();
}
}
}

10
Assets/Plugins/Best HTTP/Examples/HTTP/ResumableStreamingSample.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 972fc2301f87c9e46bfb5523f2bc5090
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

272
Assets/Plugins/Best HTTP/Examples/HTTP/StreamingSample.cs

@ -0,0 +1,272 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
namespace BestHTTP.Examples.HTTP
{
public class StreamingSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[Tooltip("The url of the resource to download")]
[SerializeField]
protected string _downloadPath = "/test100mb.dat";
[Header("Streaming Setup")]
[SerializeField]
protected RectTransform _streamingSetupRoot;
[SerializeField]
protected Slider _fragmentSizeSlider;
[SerializeField]
protected Text _fragmentSizeText;
[SerializeField]
protected Toggle _disableCacheToggle;
[Header("Reporting")]
[SerializeField]
protected RectTransform _reportingRoot;
[SerializeField]
protected Slider _downloadProgressSlider;
[SerializeField]
protected Text _downloadProgressText;
[SerializeField]
protected Slider _processedDataSlider;
[SerializeField]
protected Text _processedDataText;
[SerializeField]
protected Text _statusText;
[SerializeField]
protected Button _startDownload;
[SerializeField]
protected Button _cancelDownload;
#pragma warning restore
/// <summary>
/// Cached request to be able to abort it
/// </summary>
protected HTTPRequest request;
/// <summary>
/// Download(processing) progress. Its range is between [0..1]
/// </summary>
protected float progress;
/// <summary>
/// The fragment size that we will set to the request
/// </summary>
protected int fragmentSize = HTTPResponse.MinReadBufferSize;
protected virtual long DownloadLength { get; set; }
protected virtual long ProcessedBytes { get; set; }
protected override void Start()
{
base.Start();
this._streamingSetupRoot.gameObject.SetActive(true);
this._reportingRoot.gameObject.SetActive(false);
this._startDownload.interactable = true;
this._cancelDownload.interactable = false;
this._fragmentSizeSlider.value = (1024 * 1024 - HTTPResponse.MinReadBufferSize) / 1024;
this._fragmentSizeText.text = GUIHelper.GetBytesStr(1024 * 1024, 1);
}
protected void OnDestroy()
{
// Stop the download if we are leaving this example
if (request != null && request.State < HTTPRequestStates.Finished)
{
request.OnDownloadProgress = null;
request.Callback = null;
request.Abort();
}
}
public void OnFragmentSizeSliderChanged(float value)
{
this.fragmentSize = HTTPResponse.MinReadBufferSize + (int)value * 1024;
this._fragmentSizeText.text = GUIHelper.GetBytesStr(this.fragmentSize, 1);
}
public void Cancel()
{
if (this.request != null)
this.request.Abort();
}
protected virtual void SetupRequest()
{
request = new HTTPRequest(new Uri(base.sampleSelector.BaseURL + this._downloadPath), OnRequestFinished);
#if !BESTHTTP_DISABLE_CACHING
// If we are writing our own file set it to true(disable), so don't duplicate it on the file-system
request.DisableCache = this._disableCacheToggle.isOn;
#endif
request.StreamFragmentSize = fragmentSize;
request.Tag = DateTime.Now;
request.OnHeadersReceived += OnHeadersReceived;
request.OnDownloadProgress += OnDownloadProgress;
request.OnStreamingData += OnDataDownloaded;
}
public virtual void StartStreaming()
{
SetupRequest();
// Start Processing the request
request.Send();
this._statusText.text = "Download started!";
// UI
this._streamingSetupRoot.gameObject.SetActive(false);
this._reportingRoot.gameObject.SetActive(true);
this._startDownload.interactable = false;
this._cancelDownload.interactable = true;
ResetProcessedValues();
}
private void OnHeadersReceived(HTTPRequest req, HTTPResponse resp, Dictionary<string, List<string>> newHeaders)
{
var range = resp.GetRange();
if (range != null)
this.DownloadLength = range.ContentLength;
else
{
var contentLength = resp.GetFirstHeaderValue("content-length");
if (contentLength != null)
{
long length = 0;
if (long.TryParse(contentLength, out length))
this.DownloadLength = length;
}
}
}
protected virtual void OnRequestFinished(HTTPRequest req, HTTPResponse resp)
{
switch (req.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (resp.IsSuccess)
{
DateTime downloadStarted = (DateTime)req.Tag;
TimeSpan diff = DateTime.Now - downloadStarted;
this._statusText.text = string.Format("Streaming finished in {0:N0}ms", diff.TotalMilliseconds);
}
else
{
this._statusText.text = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
resp.StatusCode,
resp.Message,
resp.DataAsText);
Debug.LogWarning(this._statusText.text);
request = null;
}
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
this._statusText.text = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception");
Debug.LogError(this._statusText.text);
request = null;
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
this._statusText.text = "Request Aborted!";
Debug.LogWarning(this._statusText.text);
request = null;
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
this._statusText.text = "Connection Timed Out!";
Debug.LogError(this._statusText.text);
request = null;
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
this._statusText.text = "Processing the request Timed Out!";
Debug.LogError(this._statusText.text);
request = null;
break;
}
// UI
this._streamingSetupRoot.gameObject.SetActive(true);
this._reportingRoot.gameObject.SetActive(false);
this._startDownload.interactable = true;
this._cancelDownload.interactable = false;
request = null;
}
protected virtual void OnDownloadProgress(HTTPRequest originalRequest, long downloaded, long downloadLength)
{
double downloadPercent = (downloaded / (double)downloadLength) * 100;
this._downloadProgressSlider.value = (float)downloadPercent;
this._downloadProgressText.text = string.Format("{0:F1}%", downloadPercent);
}
protected virtual bool OnDataDownloaded(HTTPRequest request, HTTPResponse response, byte[] dataFragment, int dataFragmentLength)
{
this.ProcessedBytes += dataFragmentLength;
SetDataProcessedUI(this.ProcessedBytes, this.DownloadLength);
// Use downloaded data
// Return true if dataFrament is processed so the plugin can recycle the byte[]
return true;
}
protected void SetDataProcessedUI(long processed, long length)
{
float processedPercent = (processed / (float)length) * 100f;
this._processedDataSlider.value = processedPercent;
this._processedDataText.text = GUIHelper.GetBytesStr(processed, 0);
}
protected virtual void ResetProcessedValues()
{
this.ProcessedBytes = 0;
this.DownloadLength = 0;
SetDataProcessedUI(this.ProcessedBytes, this.DownloadLength);
}
}
}

11
Assets/Plugins/Best HTTP/Examples/HTTP/StreamingSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7608ce95dba469c42b49baa85e3c300c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

159
Assets/Plugins/Best HTTP/Examples/HTTP/TextureDownloadSample.cs

@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
namespace BestHTTP.Examples.HTTP
{
public sealed class TextureDownloadSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[Header("Texture Download Example")]
[Tooltip("The URL of the server that will serve the image resources")]
[SerializeField]
private string _path = "/images/Demo/";
[Tooltip("The downloadable images")]
[SerializeField]
private string[] _imageNames = new string[9] { "One.png", "Two.png", "Three.png", "Four.png", "Five.png", "Six.png", "Seven.png", "Eight.png", "Nine.png" };
[SerializeField]
private RawImage[] _images = new RawImage[0];
[SerializeField]
private Text _maxConnectionPerServerLabel;
[SerializeField]
private Text _cacheLabel;
#pragma warning restore
private byte savedMaxConnectionPerServer;
#if !BESTHTTP_DISABLE_CACHING
private bool allDownloadedFromLocalCache;
#endif
private List<HTTPRequest> activeRequests = new List<HTTPRequest>();
protected override void Start()
{
base.Start();
this.savedMaxConnectionPerServer = HTTPManager.MaxConnectionPerServer;
// Set a well observable value
// This is how many concurrent requests can be made to a server
HTTPManager.MaxConnectionPerServer = 1;
this._maxConnectionPerServerLabel.text = HTTPManager.MaxConnectionPerServer.ToString();
}
void OnDestroy()
{
// Set back to its defualt value.
HTTPManager.MaxConnectionPerServer = this.savedMaxConnectionPerServer;
foreach (var request in this.activeRequests)
request.Abort();
this.activeRequests.Clear();
}
public void OnMaxConnectionPerServerChanged(float value)
{
HTTPManager.MaxConnectionPerServer = (byte)Mathf.RoundToInt(value);
this._maxConnectionPerServerLabel.text = HTTPManager.MaxConnectionPerServer.ToString();
}
public void DownloadImages()
{
// Set these metadatas to its initial values
#if !BESTHTTP_DISABLE_CACHING
allDownloadedFromLocalCache = true;
#endif
for (int i = 0; i < _imageNames.Length; ++i)
{
// Set a blank placeholder texture, overriding previously downloaded texture
this._images[i].texture = null;
// Construct the request
var request = new HTTPRequest(new Uri(this.sampleSelector.BaseURL + this._path + this._imageNames[i]), ImageDownloaded);
// Set the Tag property, we can use it as a general storage bound to the request
request.Tag = this._images[i];
// Send out the request
request.Send();
this.activeRequests.Add(request);
}
this._cacheLabel.text = string.Empty;
}
/// <summary>
/// Callback function of the image download http requests
/// </summary>
void ImageDownloaded(HTTPRequest req, HTTPResponse resp)
{
switch (req.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (resp.IsSuccess)
{
// The target RawImage reference is stored in the Tag property
RawImage rawImage = req.Tag as RawImage;
rawImage.texture = resp.DataAsTexture2D;
#if !BESTHTTP_DISABLE_CACHING
// Update the cache-info variable
allDownloadedFromLocalCache = allDownloadedFromLocalCache && resp.IsFromCache;
#endif
}
else
{
Debug.LogWarning(string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
resp.StatusCode,
resp.Message,
resp.DataAsText));
}
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
Debug.LogError("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
Debug.LogWarning("Request Aborted!");
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
Debug.LogError("Connection Timed Out!");
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
Debug.LogError("Processing the request Timed Out!");
break;
}
this.activeRequests.Remove(req);
if (this.activeRequests.Count == 0)
{
#if !BESTHTTP_DISABLE_CACHING
if (this.allDownloadedFromLocalCache)
this._cacheLabel.text = "All images loaded from local cache!";
else
#endif
this._cacheLabel.text = string.Empty;
}
}
}
}

10
Assets/Plugins/Best HTTP/Examples/HTTP/TextureDownloadSample.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: af6ffe2bbf96d2b49ba3ef0713511d45
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

222
Assets/Plugins/Best HTTP/Examples/HTTP/UploadStream.cs

@ -0,0 +1,222 @@
using BestHTTP;
using System;
using System.IO;
using System.Threading;
namespace BestHTTP.Examples
{
public sealed class UploadStream : Stream
{
#region Private Fields
/// <summary>
/// Buffer for reads
/// </summary>
MemoryStream ReadBuffer = new MemoryStream();
/// <summary>
/// Buffer for writes
/// </summary>
MemoryStream WriteBuffer = new MemoryStream();
/// <summary>
/// Indicates that we will not write more data to this stream
/// </summary>
bool noMoreData;
/// <summary>
/// For thread synchronization
/// </summary>
AutoResetEvent ARE = new AutoResetEvent(false);
/// <summary>
/// For thread synchronization
/// </summary>
object locker = new object();
#endregion
#region Properties
/// <summary>
/// Name of this stream for easier debugging
/// </summary>
public string Name { get; private set; }
/// <summary>
/// true if we are read all data from the read buffer
/// </summary>
private bool IsReadBufferEmpty { get { lock (locker) return ReadBuffer.Position == ReadBuffer.Length; } }
#endregion
#region Constructors
public UploadStream(string name)
: this()
{
this.Name = name;
}
public UploadStream()
{
this.ReadBuffer = new MemoryStream();
this.WriteBuffer = new MemoryStream();
this.Name = string.Empty;
}
#endregion
#region Stream Implementation
public override int Read(byte[] buffer, int offset, int count)
{
// We will not push more data to the write buffer
if (noMoreData)
{
// No data left in the read buffer
if (ReadBuffer.Position == ReadBuffer.Length)
{
// Is there any data in the write buffer? If so, switch the buffers
if (WriteBuffer.Length > 0)
SwitchBuffers();
else
{
HTTPManager.Logger.Information("UploadStream", string.Format("{0} - Read - End Of Stream", this.Name));
return -1;
}
}
else
return ReadBuffer.Read(buffer, offset, count);
}
// There are no more data in the read buffer? Wait for it.
if (IsReadBufferEmpty)
{
ARE.WaitOne();
lock (locker)
if (IsReadBufferEmpty && WriteBuffer.Length > 0)
SwitchBuffers();
}
int read = -1;
lock (locker)
read = ReadBuffer.Read(buffer, offset, count);
return read;
}
public override void Write(byte[] buffer, int offset, int count)
{
if (noMoreData)
throw new System.ArgumentException("noMoreData already set!");
lock (locker)
{
WriteBuffer.Write(buffer, offset, count);
SwitchBuffers();
}
ARE.Set();
}
public override void Flush()
{
Finish();
}
#endregion
#region Dispose Implementation
protected override void Dispose(bool disposing)
{
if (disposing)
{
HTTPManager.Logger.Information("UploadStream", string.Format("{0} - Dispose", this.Name));
ReadBuffer.Dispose();
ReadBuffer = null;
WriteBuffer.Dispose();
WriteBuffer = null;
#if NETFX_CORE
ARE.Dispose();
#else
ARE.Close();
#endif
ARE = null;
}
base.Dispose(disposing);
}
#endregion
#region Helper Functions
public void Finish()
{
if (noMoreData)
throw new System.ArgumentException("noMoreData already set!");
HTTPManager.Logger.Information("UploadStream", string.Format("{0} - Finish", this.Name));
noMoreData = true;
ARE.Set();
}
private bool SwitchBuffers()
{
// Switch the buffers only when all data are consumed from our read buffer
lock (locker)
{
if (ReadBuffer.Position == ReadBuffer.Length)
{
// This buffer will be the read buffer, we need to seek back to the beginning
WriteBuffer.Seek(0, SeekOrigin.Begin);
// This will be the write buffer, set the length to zero
ReadBuffer.SetLength(0);
// switch the two buffers
MemoryStream tmp = WriteBuffer;
WriteBuffer = ReadBuffer;
ReadBuffer = tmp;
return true;
}
}
return false;
}
#endregion
#region Not Implemented Functions and Properties
public override bool CanRead { get { throw new NotImplementedException(); } }
public override bool CanSeek { get { throw new NotImplementedException(); } }
public override bool CanWrite { get { throw new NotImplementedException(); } }
public override long Length { get { throw new NotImplementedException(); } }
public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
#endregion
}
}

10
Assets/Plugins/Best HTTP/Examples/HTTP/UploadStream.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a2ab021301a7baf45a80b5a46275a140
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/Helpers.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e17235d56e1e78642af36ef4d6dcee27
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/Helpers/Components.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 514e2a6c85b1e3644b534eb9c892fff9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

57
Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cache.cs

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using BestHTTP.Core;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.Components
{
public class Cache : MonoBehaviour
{
#pragma warning disable 0649, 0169
[SerializeField]
private Text _count;
[SerializeField]
private Text _size;
[SerializeField]
private Button _clear;
#pragma warning restore
private void Start()
{
PluginEventHelper.OnEvent += OnPluginEvent;
UpdateLabels();
}
private void OnDestroy()
{
PluginEventHelper.OnEvent -= OnPluginEvent;
}
private void OnPluginEvent(PluginEventInfo @event)
{
if (@event.Event == PluginEvents.SaveCacheLibrary)
UpdateLabels();
}
private void UpdateLabels()
{
#if !BESTHTTP_DISABLE_CACHING
this._count.text = BestHTTP.Caching.HTTPCacheService.GetCacheEntityCount().ToString("N0");
this._size.text = BestHTTP.Caching.HTTPCacheService.GetCacheSize().ToString("N0");
#else
this._count.text = "0";
this._size.text = "0";
#endif
}
public void OnClearButtonClicked()
{
#if !BESTHTTP_DISABLE_CACHING
BestHTTP.Caching.HTTPCacheService.BeginClear();
#endif
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cache.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b640e13d843caef4885814c6d13d8e3d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

63
Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cookies.cs

@ -0,0 +1,63 @@
using BestHTTP.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.Components
{
public class Cookies : MonoBehaviour
{
#pragma warning disable 0649, 0169
[SerializeField]
private Text _count;
[SerializeField]
private Text _size;
[SerializeField]
private Button _clear;
#pragma warning restore
private void Start()
{
PluginEventHelper.OnEvent += OnPluginEvent;
UpdateLabels();
}
private void OnDestroy()
{
PluginEventHelper.OnEvent -= OnPluginEvent;
}
private void OnPluginEvent(PluginEventInfo @event)
{
#if !BESTHTTP_DISABLE_COOKIES
if (@event.Event == PluginEvents.SaveCookieLibrary)
UpdateLabels();
#endif
}
private void UpdateLabels()
{
#if !BESTHTTP_DISABLE_COOKIES
var cookies = BestHTTP.Cookies.CookieJar.GetAll();
var size = cookies.Sum(c => c.GuessSize());
this._count.text = cookies.Count.ToString("N0");
this._size.text = size.ToString("N0");
#else
this._count.text = "0";
this._size.text = "0";
#endif
}
public void OnClearButtonClicked()
{
#if !BESTHTTP_DISABLE_COOKIES
BestHTTP.Cookies.CookieJar.Clear();
#endif
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/Components/Cookies.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b9db2d0fa31b054b835fb38d688f211
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

60
Assets/Plugins/Best HTTP/Examples/Helpers/GUIHelper.cs

@ -0,0 +1,60 @@
using BestHTTP.Examples.Helpers;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples
{
public static class GUIHelper
{
// https://en.wikipedia.org/wiki/Binary_prefix
private static string[] prefixes = new string[] { " B", " KiB", " MiB", " GiB", " TiB" };
public static string GetBytesStr(double bytes, byte precision)
{
int prefixIdx = 0;
while (bytes >= 1024)
{
bytes = bytes / 1024;
prefixIdx++;
}
return bytes.ToString("F" + precision) + prefixes[prefixIdx];
}
public static void RemoveChildren(RectTransform transform, int maxChildCount)
{
while (transform.childCount > maxChildCount)
{
var child = transform.GetChild(0);
child.SetParent(null);
GameObject.Destroy(child.gameObject);
}
}
public static TextListItem AddText(TextListItem prefab, RectTransform contentRoot, string text, int maxEntries, ScrollRect scrollRect)
{
if (contentRoot == null)
return null;
var listItem = GameObject.Instantiate<TextListItem>(prefab, contentRoot, false);
listItem.SetText(text);
GUIHelper.RemoveChildren(contentRoot, maxEntries);
if (scrollRect != null && scrollRect.isActiveAndEnabled)
scrollRect.StartCoroutine(ScrollToBottom(scrollRect));
return listItem;
}
public static IEnumerator ScrollToBottom(ScrollRect scrollRect)
{
yield return null;
if (scrollRect != null && scrollRect.isActiveAndEnabled)
scrollRect.normalizedPosition = new Vector2(0, 0);
}
}
}

10
Assets/Plugins/Best HTTP/Examples/Helpers/GUIHelper.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: fd560ff6f0fa60844a43a82db1ad03be
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

36
Assets/Plugins/Best HTTP/Examples/Helpers/Link.cs

@ -0,0 +1,36 @@
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.EventSystems;
namespace BestHTTP.Examples
{
public class Link : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler
{
public string url;
public Texture2D linkSelectCursor;
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
{
#if UNITY_WEBGL && !UNITY_EDITOR
openWindow(this.url);
#else
Application.OpenURL(this.url);
#endif
}
void IPointerEnterHandler.OnPointerEnter(PointerEventData eventData)
{
Cursor.SetCursor(this.linkSelectCursor, Vector2.zero, CursorMode.Auto);
}
void IPointerExitHandler.OnPointerExit(PointerEventData eventData)
{
Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
}
#if UNITY_WEBGL && !UNITY_EDITOR
[DllImport("__Internal")]
private static extern void openWindow(string url);
#endif
}
}

13
Assets/Plugins/Best HTTP/Examples/Helpers/Link.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 3ab0e37de384a5b4d8320cdd8644b44c
timeCreated: 1572211254
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

23
Assets/Plugins/Best HTTP/Examples/Helpers/SampleBase.cs

@ -0,0 +1,23 @@
using UnityEngine;
namespace BestHTTP.Examples.Helpers
{
public abstract class SampleBase : MonoBehaviour
{
[Header("Common Properties")]
public string Category;
public string DisplayName;
[TextArea]
public string Description;
public RuntimePlatform[] BannedPlatforms = new RuntimePlatform[0];
protected SampleRoot sampleSelector;
protected virtual void Start()
{
this.sampleSelector = FindObjectOfType<SampleRoot>();
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/SampleBase.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f8792c52d9520447a1c9d7139925f57
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: beedbf79e87c74949aa50c9220fdf55c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

22
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/Category.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.SelectorUI
{
public sealed class Category : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField]
private Text _text;
#pragma warning restore
public void SetLabel(string category)
{
this._text.text = category;
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/Category.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1101c9e1e1276414d8062a6a7ca4db45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

37
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleInfo.cs

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.SelectorUI
{
public sealed class ExampleInfo : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField]
private Text _header;
[SerializeField]
private Text _description;
#pragma warning restore
private SampleSelectorUI _parentUI;
private SampleBase _example;
public void Setup(SampleSelectorUI parentUI, SampleBase example)
{
this._parentUI = parentUI;
this._example = example;
this._header.text = this._example.name;
this._description.text = this._example.Description;
}
public void OnExecuteExample()
{
this._parentUI.ExecuteExample(this._example);
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleInfo.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fd424cc4259865c4ba2fb4d9d68d0272
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

32
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleListItem.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.SelectorUI
{
public sealed class ExampleListItem : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField]
private Text _text;
#pragma warning restore
public SampleSelectorUI ParentUI { get; private set; }
public SampleBase ExamplePrefab { get; private set; }
public void Setup(SampleSelectorUI parentUI, SampleBase prefab)
{
this.ParentUI = parentUI;
this.ExamplePrefab = prefab;
this._text.text = prefab.DisplayName;
}
public void OnButton()
{
this.ParentUI.SelectSample(this);
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/ExampleListItem.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 376fb4eb0776e41479fb60f520aaa1f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

101
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/SampleSelectorUI.cs

@ -0,0 +1,101 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers.SelectorUI
{
public class SampleSelectorUI : MonoBehaviour
{
#pragma warning disable 0649, 0169
[SerializeField]
private Category _categoryListItemPrefab;
[SerializeField]
private ExampleListItem _exampleListItemPrefab;
[SerializeField]
private ExampleInfo _exampleInfoPrefab;
[SerializeField]
private RectTransform _listRoot;
[SerializeField]
private RectTransform _dyncamicContentRoot;
private SampleRoot sampleSelector;
private ExampleListItem selectedSample;
private GameObject dynamicContent;
#pragma warning restore
private void Start()
{
this.sampleSelector = FindObjectOfType<SampleRoot>();
DisplayExamples();
}
private void DisplayExamples()
{
// Sort examples by category
this.sampleSelector.samples.Sort((a, b) => {
if (a == null || b == null)
return 0;
int result = a.Category.CompareTo(b.Category);
if (result == 0)
result = a.DisplayName.CompareTo(b.DisplayName);
return result;
});
string currentCategory = null;
for (int i = 0; i < this.sampleSelector.samples.Count; ++i)
{
var examplePrefab = this.sampleSelector.samples[i];
if (examplePrefab == null)
continue;
if (examplePrefab.BannedPlatforms.Contains(UnityEngine.Application.platform))
continue;
if (currentCategory != examplePrefab.Category)
{
var category = Instantiate<Category>(this._categoryListItemPrefab, this._listRoot, false);
category.SetLabel(examplePrefab.Category);
currentCategory = examplePrefab.Category;
}
var listItem = Instantiate<ExampleListItem>(this._exampleListItemPrefab, this._listRoot, false);
listItem.Setup(this, examplePrefab);
if (this.sampleSelector.selectedExamplePrefab == null)
{
SelectSample(listItem);
}
}
}
public void SelectSample(ExampleListItem item)
{
this.sampleSelector.selectedExamplePrefab = item.ExamplePrefab;
if (this.dynamicContent != null)
Destroy(this.dynamicContent);
var example = Instantiate<ExampleInfo>(this._exampleInfoPrefab, this._dyncamicContentRoot, false);
example.Setup(this, item.ExamplePrefab);
this.dynamicContent = example.gameObject;
}
public void ExecuteExample(SampleBase example)
{
if (this.dynamicContent != null)
Destroy(this.dynamicContent);
this.dynamicContent = Instantiate(example, this._dyncamicContentRoot, false).gameObject;
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/SelectorUI/SampleSelectorUI.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd639b2a784de314984c606b7e8329e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

26
Assets/Plugins/Best HTTP/Examples/Helpers/TextListItem.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers
{
public class TextListItem : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField]
private Text _text;
#pragma warning restore
public void SetText(string text)
{
this._text.text = text;
}
public void AddLeftPadding(int padding)
{
this.GetComponent<LayoutGroup>().padding.left += padding;
}
}
}

11
Assets/Plugins/Best HTTP/Examples/Helpers/TextListItem.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05975660b0231b84f849693106b207d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/Plugin.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 255df445982551d4cbbcf8238aee20f7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

57
Assets/Plugins/Best HTTP/Examples/Plugin/AsyncExtensions.cs

@ -0,0 +1,57 @@
#if CSHARP_7_OR_LATER
using System;
using System.Threading;
using System.Threading.Tasks;
namespace BestHTTP
{
public static class AsyncExtensions
{
public static Task<T> GetFromJsonResultAsync<T>(this HTTPRequest request, CancellationToken token = default)
{
return HTTPRequestAsyncExtensions.CreateTask<T>(request, token, (req, resp, tcs) =>
{
switch (req.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (resp.IsSuccess)
tcs.TrySetResult(BestHTTP.JSON.LitJson.JsonMapper.ToObject<T>(resp.DataAsText));
else
tcs.TrySetException(HTTPRequestAsyncExtensions.CreateException("Request finished Successfully, but the server sent an error.", resp));
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
HTTPRequestAsyncExtensions.VerboseLogging(request, "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
tcs.TrySetException(HTTPRequestAsyncExtensions.CreateException("No Exception", null, req.Exception));
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
HTTPRequestAsyncExtensions.VerboseLogging(request, "Request Aborted!");
tcs.TrySetCanceled();
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
HTTPRequestAsyncExtensions.VerboseLogging(request, "Connection Timed Out!");
tcs.TrySetException(HTTPRequestAsyncExtensions.CreateException("Connection Timed Out!"));
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
HTTPRequestAsyncExtensions.VerboseLogging(request, "Processing the request Timed Out!");
tcs.TrySetException(HTTPRequestAsyncExtensions.CreateException("Processing the request Timed Out!"));
break;
}
});
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/Plugin/AsyncExtensions.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f0aefe97b2a43844850d2d8b234e819
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

103
Assets/Plugins/Best HTTP/Examples/SampleRoot.cs

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP.Examples.Helpers;
namespace BestHTTP.Examples
{
public class SampleRoot : MonoBehaviour
{
#pragma warning disable 0649, 0169
[Header("Common Properties")]
public string BaseURL = "https://besthttpwebgldemo.azurewebsites.net";
[Header("References")]
[SerializeField]
private Text _pluginVersion;
[SerializeField]
private Dropdown _logLevelDropdown;
[SerializeField]
private Text _proxyLabel;
[SerializeField]
private InputField _proxyInputField;
#pragma warning restore
[SerializeField]
public List<SampleBase> samples = new List<SampleBase>();
[HideInInspector]
public SampleBase selectedExamplePrefab;
private void Start()
{
Application.runInBackground = true;
this._pluginVersion.text = "Version: " + HTTPManager.UserAgent;
int logLevel = PlayerPrefs.GetInt("BestHTTP.HTTPManager.Logger.Level", (int)HTTPManager.Logger.Level);
this._logLevelDropdown.value = logLevel;
HTTPManager.Logger.Level = (BestHTTP.Logger.Loglevels)logLevel;
#if (UNITY_WEBGL && !UNITY_EDITOR) || BESTHTTP_DISABLE_PROXY
this._proxyLabel.gameObject.SetActive(false);
this._proxyInputField.gameObject.SetActive(false);
#else
string proxyURL = PlayerPrefs.GetString("BestHTTP.HTTPManager.Proxy", null);
if (!string.IsNullOrEmpty(proxyURL))
{
try
{
HTTPManager.Proxy = new HTTPProxy(new Uri(proxyURL), null, true);
#if UNITY_2019_1_OR_NEWER
this._proxyInputField.SetTextWithoutNotify(proxyURL);
#else
this._proxyInputField.onEndEdit.RemoveAllListeners();
this._proxyInputField.text = proxyURL;
this._proxyInputField.onEndEdit.AddListener(this.OnProxyEditEnd);
#endif
}
catch
{ }
}
else
HTTPManager.Proxy = null;
#endif
#if !BESTHTTP_DISABLE_CACHING
// Remove too old cache entries.
BestHTTP.Caching.HTTPCacheService.BeginMaintainence(new BestHTTP.Caching.HTTPCacheMaintananceParams(TimeSpan.FromDays(30), ulong.MaxValue));
#endif
}
public void OnLogLevelChanged(int idx)
{
HTTPManager.Logger.Level = (BestHTTP.Logger.Loglevels)idx;
PlayerPrefs.SetInt("BestHTTP.HTTPManager.Logger.Level", idx);
}
public void OnProxyEditEnd(string proxyURL)
{
#if (!UNITY_WEBGL || UNITY_EDITOR) && !BESTHTTP_DISABLE_PROXY
try
{
if (string.IsNullOrEmpty(this._proxyInputField.text))
HTTPManager.Proxy = null;
else
HTTPManager.Proxy = new HTTPProxy(new Uri(this._proxyInputField.text), null, true);
PlayerPrefs.SetString("BestHTTP.HTTPManager.Proxy", this._proxyInputField.text);
}
catch
{ }
#endif
}
}
}

13
Assets/Plugins/Best HTTP/Examples/SampleRoot.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 0eb115c0377f90041a9ecfde21658f92
timeCreated: 1571213708
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/Server-Sent Events.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b86f7bd69606df2419df60d808328c1b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

156
Assets/Plugins/Best HTTP/Examples/Server-Sent Events/SimpleSample.cs

@ -0,0 +1,156 @@
#if !BESTHTTP_DISABLE_SERVERSENT_EVENTS
using System;
using BestHTTP.Examples.Helpers;
using BestHTTP.ServerSentEvents;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.ServerSentEvents
{
public class SimpleSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[Tooltip("The url of the resource to use.")]
[SerializeField]
private string _path = "/sse";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _startButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
private EventSource eventSource;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (this.eventSource != null)
{
this.eventSource.Close();
this.eventSource = null;
}
}
public void OnStartButton()
{
GUIHelper.RemoveChildren(this._contentRoot, 0);
// Create the EventSource instance
this.eventSource = new EventSource(new Uri(base.sampleSelector.BaseURL + this._path));
// Subscribe to generic events
this.eventSource.OnOpen += OnOpen;
this.eventSource.OnClosed += OnClosed;
this.eventSource.OnError += OnError;
this.eventSource.OnStateChanged += this.OnStateChanged;
this.eventSource.OnMessage += OnMessage;
// Subscribe to an application specific event
this.eventSource.On("datetime", OnDateTime);
// Start to connect to the server
this.eventSource.Open();
AddText("Opening Server-Sent Events...");
SetButtons(false, true);
}
public void OnCloseButton()
{
SetButtons(false, false);
this.eventSource.Close();
}
private void OnOpen(EventSource eventSource)
{
AddText("Open");
}
private void OnClosed(EventSource eventSource)
{
AddText("Closed");
this.eventSource = null;
SetButtons(true, false);
}
private void OnError(EventSource eventSource, string error)
{
AddText(string.Format("Error: <color=red>{0}</color>", error));
}
private void OnStateChanged(EventSource eventSource, States oldState, States newState)
{
AddText(string.Format("State Changed {0} => {1}", oldState, newState));
}
private void OnMessage(EventSource eventSource, Message message)
{
AddText(string.Format("Message: <color=yellow>{0}</color>", message));
}
private void OnDateTime(EventSource eventSource, Message message)
{
DateTimeData dtData = BestHTTP.JSON.LitJson.JsonMapper.ToObject<DateTimeData>(message.Data);
AddText(string.Format("OnDateTime: <color=yellow>{0}</color>", dtData.ToString()));
}
private void SetButtons(bool start, bool close)
{
if (this._startButton != null)
this._startButton.interactable = start;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private void AddText(string text)
{
GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
[PlatformSupport.IL2CPP.Preserve]
sealed class DateTimeData
{
#pragma warning disable 0649
[PlatformSupport.IL2CPP.Preserve]
public int eventid;
[PlatformSupport.IL2CPP.Preserve]
public string datetime;
#pragma warning restore
public override string ToString()
{
return string.Format("[DateTimeData EventId: {0}, DateTime: {1}]", this.eventid, this.datetime);
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/Server-Sent Events/SimpleSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 730e176dfa30cb24c93efcaabb4f8688
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalR.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 56e6fe2f6b3c19848aec5ffe33186e61
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8894a3d3eb906a64a8173b7f1016fed5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

135
Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleCookieAuthentication.cs

@ -0,0 +1,135 @@
#if !BESTHTTP_DISABLE_SIGNALR
#if !BESTHTTP_DISABLE_COOKIES && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using BestHTTP.Cookies;
using BestHTTP.SignalR.Transports;
namespace BestHTTP.SignalR.Authentication
{
public sealed class SampleCookieAuthentication : IAuthenticationProvider
{
#region Public Properties
public Uri AuthUri { get; private set; }
public string UserName { get; private set; }
public string Password { get; private set; }
public string UserRoles { get; private set; }
#endregion
#region IAuthenticationProvider properties
public bool IsPreAuthRequired { get; private set; }
public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;
public event OnAuthenticationFailedDelegate OnAuthenticationFailed;
#endregion
#region Privates
private HTTPRequest AuthRequest;
private Cookie Cookie;
#endregion
public SampleCookieAuthentication(Uri authUri, string user, string passwd, string roles)
{
this.AuthUri = authUri;
this.UserName = user;
this.Password = passwd;
this.UserRoles = roles;
this.IsPreAuthRequired = true;
}
#region IAuthenticationProvider Implementation
public void StartAuthentication()
{
AuthRequest = new HTTPRequest(AuthUri, HTTPMethods.Post, OnAuthRequestFinished);
// Setup the form
AuthRequest.AddField("userName", UserName);
AuthRequest.AddField("Password", Password); // not used in the sample
AuthRequest.AddField("roles", UserRoles);
AuthRequest.Send();
}
public void PrepareRequest(HTTPRequest request, RequestTypes type)
{
// Adding the cookie to the request is not required, as it's managed by the plugin automatically,
// but for now, we want to be really sure that it's added
request.Cookies.Add(Cookie);
}
#endregion
#region Request Handler
void OnAuthRequestFinished(HTTPRequest req, HTTPResponse resp)
{
AuthRequest = null;
string failReason = string.Empty;
switch (req.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (resp.IsSuccess)
{
Cookie = resp.Cookies != null ? resp.Cookies.Find(c => c.Name.Equals(".ASPXAUTH")) : null;
if (Cookie != null)
{
HTTPManager.Logger.Information("CookieAuthentication", "Auth. Cookie found!");
if (OnAuthenticationSucceded != null)
OnAuthenticationSucceded(this);
// return now, all other paths are authentication failures
return;
}
else
HTTPManager.Logger.Warning("CookieAuthentication", failReason = "Auth. Cookie NOT found!");
}
else
HTTPManager.Logger.Warning("CookieAuthentication", failReason = string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
resp.StatusCode,
resp.Message,
resp.DataAsText));
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
HTTPManager.Logger.Warning("CookieAuthentication", failReason = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
HTTPManager.Logger.Warning("CookieAuthentication", failReason = "Request Aborted!");
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
HTTPManager.Logger.Error("CookieAuthentication", failReason = "Connection Timed Out!");
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
HTTPManager.Logger.Error("CookieAuthentication", failReason = "Processing the request Timed Out!");
break;
}
if (OnAuthenticationFailed != null)
OnAuthenticationFailed(this, failReason);
}
#endregion
}
}
#endif
#endif

10
Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleCookieAuthentication.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 48a74a50eeb07bb4ea649a902e9d487a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

97
Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleHeaderAuthentication.cs

@ -0,0 +1,97 @@
#if !BESTHTTP_DISABLE_SIGNALR
namespace BestHTTP.SignalR.Authentication
{
/// <summary>
/// Custom http-header based authenticator.
/// <example>
/// <code>
/// // Server side implementation of the Header-based authenticator
/// // Use it by adding the app.Use(typeof(HeaderBasedAuthenticationMiddleware)); line to the Startup class' Configuration function.
/// private class HeaderBasedAuthenticationMiddleware : OwinMiddleware
/// {
/// public HeaderBasedAuthenticationMiddleware(OwinMiddleware next)
/// : base(next)
/// {
/// }
///
/// public override Task Invoke(IOwinContext context)
/// {
/// string username = context.Request.Headers.Get("username");
/// string roles = context.Request.Headers.Get("roles");
///
/// if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(roles))
/// {
/// var identity = new System.Security.Principal.GenericIdentity(username);
///
/// var principal = new System.Security.Principal.GenericPrincipal(identity, SplitString(roles));
///
/// context.Request.User = principal;
/// }
///
/// return Next.Invoke(context);
/// }
///
/// private static string[] SplitString(string original)
/// {
/// if (String.IsNullOrEmpty(original))
/// return new string[0];
///
/// var split = from piece in original.Split(',') let trimmed = piece.Trim() where !String.IsNullOrEmpty(trimmed) select trimmed;
///
/// return split.ToArray();
/// }
/// }
/// </code>
/// </example>
/// </summary>
class HeaderAuthenticator : IAuthenticationProvider
{
public string User { get; private set; }
public string Roles { get; private set; }
/// <summary>
/// No pre-auth step required for this type of authentication
/// </summary>
public bool IsPreAuthRequired { get { return false; } }
#pragma warning disable 0067
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationFailedDelegate OnAuthenticationFailed;
#pragma warning restore 0067
/// <summary>
/// Constructor to initialise the authenticator with username and roles.
/// </summary>
public HeaderAuthenticator(string user, string roles)
{
this.User = user;
this.Roles = roles;
}
/// <summary>
/// Not used as IsPreAuthRequired is false
/// </summary>
public void StartAuthentication()
{ }
/// <summary>
/// Prepares the request by adding two headers to it
/// </summary>
public void PrepareRequest(BestHTTP.HTTPRequest request, RequestTypes type)
{
request.SetHeader("username", this.User);
request.SetHeader("roles", this.Roles);
}
}
}
#endif

10
Assets/Plugins/Best HTTP/Examples/SignalR/Authentication Providers/SampleHeaderAuthentication.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5ebd4ce02d369a6498f9be6bb7141ac3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1a071702f6b0d014890a15a301be0af9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

23
Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/JSonDotnetEncoder.cs

@ -0,0 +1,23 @@
#if !BESTHTTP_DISABLE_SIGNALR && BESTHTTP_SIGNALR_WITH_JSONDOTNET
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BestHTTP.SignalR.JsonEncoders
{
public sealed class JSonDotnetEncoder : IJsonEncoder
{
public string Encode(object obj)
{
return JsonConvert.SerializeObject(obj);
}
public IDictionary<string, object> DecodeMessage(string json)
{
return JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
}
}
}
#endif

10
Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/JSonDotnetEncoder.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 653a0f163689052438748b7beda14886
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

28
Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/LitJsonEncoder.cs

@ -0,0 +1,28 @@
#if !BESTHTTP_DISABLE_SIGNALR
using System.Collections.Generic;
using BestHTTP.JSON.LitJson;
namespace BestHTTP.SignalR.JsonEncoders
{
public sealed class LitJsonEncoder : IJsonEncoder
{
public string Encode(object obj)
{
JsonWriter writer = new JsonWriter();
JsonMapper.ToJson(obj, writer);
return writer.ToString();
}
public IDictionary<string, object> DecodeMessage(string json)
{
JsonReader reader = new JsonReader(json);
return JsonMapper.ToObject<Dictionary<string, object>>(reader);
}
}
}
#endif

10
Assets/Plugins/Best HTTP/Examples/SignalR/Json Encoders/LitJsonEncoder.cs.meta

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2870a746a601b8b439c495ff39474385
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalRCore.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22c3e67505eddc1498b5cc3253d3ee1c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

240
Assets/Plugins/Best HTTP/Examples/SignalRCore/AsyncTestHubSample.cs

@ -0,0 +1,240 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using System;
using UnityEngine;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using UnityEngine.UI;
using BestHTTP.Examples.Helpers;
#if CSHARP_7_OR_LATER
using System.Threading.Tasks;
#endif
namespace BestHTTP.Examples
{
// Server side of this example can be found here:
// https://github.com/Benedicht/BestHTTP_DemoSite/blob/master/BestHTTP_DemoSite/Hubs/TestHub.cs
public class AsyncTestHubSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
#pragma warning disable 0414
[SerializeField]
private string _path = "/TestHub";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
// Instance of the HubConnection
HubConnection hub;
protected override void Start()
{
base.Start();
#if !CSHARP_7_OR_LATER
AddText("<color=red>This sample can work only when at least c# 7.3 is supported!</color>");
SetButtons(false, false);
#else
SetButtons(true, false);
#endif
}
#if CSHARP_7_OR_LATER
async void OnDestroy()
{
await hub?.CloseAsync();
}
#endif
/// <summary>
/// GUI button callback
/// </summary>
public
#if CSHARP_7_OR_LATER
async
#endif
void OnConnectButton()
{
#if CSHARP_7_OR_LATER
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(this.sampleSelector.BaseURL + this._path), protocol);
// Subscribe to hub events
hub.OnError += Hub_OnError;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// Set up server callable functions
hub.On("Send", (string arg) => AddText(string.Format("On '<color=green>Send</color>': '<color=yellow>{0}</color>'", arg)).AddLeftPadding(20));
hub.On<Person>("Person", (person) => AddText(string.Format("On '<color=green>Person</color>': '<color=yellow>{0}</color>'", person)).AddLeftPadding(20));
hub.On<Person, Person>("TwoPersons", (person1, person2) => AddText(string.Format("On '<color=green>TwoPersons</color>': '<color=yellow>{0}</color>', '<color=yellow>{1}</color>'", person1, person2)).AddLeftPadding(20));
AddText("StartConnect called");
SetButtons(false, false);
// And finally start to connect to the server
await hub.ConnectAsync();
SetButtons(false, true);
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
// Call a server function with a string param. We expect no return value.
await hub.SendAsync("Send", "my message");
// Call a parameterless function. We expect a string return value.
try
{
string result = await hub.InvokeAsync<string>("NoParam");
AddText(string.Format("'<color=green>NoParam</color>' returned: '<color=yellow>{0}</color>'", result))
.AddLeftPadding(20);
}
catch (Exception ex)
{
AddText(string.Format("'<color=green>NoParam</color>' error: '<color=red>{0}</color>'", ex.Message)).AddLeftPadding(20);
}
// Call a function on the server to add two numbers. OnSuccess will be called with the result and OnError if there's an error.
var addResult = await hub.InvokeAsync<int>("Add", 10, 20);
AddText(string.Format("'<color=green>Add(10, 20)</color>' returned: '<color=yellow>{0}</color>'", addResult)).AddLeftPadding(20);
var nullabelTestResult = await hub.InvokeAsync<int?>("NullableTest", 10);
AddText(string.Format("'<color=green>NullableTest(10)</color>' returned: '<color=yellow>{0}</color>'", nullabelTestResult)).AddLeftPadding(20);
// Call a function that will return a Person object constructed from the function's parameters.
var getPersonResult = await hub.InvokeAsync<Person>("GetPerson", "Mr. Smith", 26);
AddText(string.Format("'<color=green>GetPerson(\"Mr. Smith\", 26)</color>' returned: '<color=yellow>{0}</color>'", getPersonResult)).AddLeftPadding(20);
// To test errors/exceptions this call always throws an exception on the server side resulting in an OnError call.
// OnError expected here!
try
{
var singleResultFailureResult = await hub.InvokeAsync<int>("SingleResultFailure", 10, 20);
AddText(string.Format("'<color=green>SingleResultFailure(10, 20)</color>' returned: '<color=yellow>{0}</color>'", singleResultFailureResult)).AddLeftPadding(20);
}
catch (Exception ex)
{
AddText(string.Format("'<color=green>SingleResultFailure(10, 20)</color>' error: '<color=red>{0}</color>'", ex.Message)).AddLeftPadding(20);
}
// This call demonstrates IEnumerable<> functions, result will be the yielded numbers.
var batchedResult = await hub.InvokeAsync<int[]>("Batched", 10);
AddText(string.Format("'<color=green>Batched(10)</color>' returned items: '<color=yellow>{0}</color>'", batchedResult.Length)).AddLeftPadding(20);
// OnItem is called for a streaming request for every items returned by the server. OnSuccess will still be called with all the items.
hub.GetDownStreamController<int>("ObservableCounter", 10, 1000)
.OnItem(result => AddText(string.Format("'<color=green>ObservableCounter(10, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>ObservableCounter(10, 1000)</color>' OnSuccess.").AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>ObservableCounter(10, 1000)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// A stream request can be cancelled any time.
var controller = hub.GetDownStreamController<int>("ChannelCounter", 10, 1000);
controller.OnItem(result => AddText(string.Format("'<color=green>ChannelCounter(10, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>ChannelCounter(10, 1000)</color>' OnSuccess.").AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>ChannelCounter(10, 1000)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// a stream can be cancelled by calling the controller's Cancel method
controller.Cancel();
// This call will stream strongly typed objects
hub.GetDownStreamController<Person>("GetRandomPersons", 20, 2000)
.OnItem(result => AddText(string.Format("'<color=green>GetRandomPersons(20, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>GetRandomPersons(20, 1000)</color>' OnSuccess.").AddLeftPadding(20));
#endif
}
/// <summary>
/// GUI button callback
/// </summary>
public
#if CSHARP_7_OR_LATER
async
#endif
void OnCloseButton()
{
#if CSHARP_7_OR_LATER
if (this.hub != null)
{
AddText("Calling CloseAsync");
SetButtons(false, false);
await this.hub.CloseAsync();
SetButtons(true, false);
AddText("Hub Closed");
}
#endif
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
SetButtons(true, false);
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private TextListItem AddText(string text)
{
return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
}
#endif

13
Assets/Plugins/Best HTTP/Examples/SignalRCore/AsyncTestHubSample.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e516808e7e284014c8b7afb3ff270943
timeCreated: 1577715218
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d8c1ea4e11d6be6488ad882939d63018
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

68
Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers/HeaderAuthenticator.cs

@ -0,0 +1,68 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using System;
namespace BestHTTP.SignalRCore.Authentication
{
public sealed class HeaderAuthenticator : IAuthenticationProvider
{
/// <summary>
/// No pre-auth step required for this type of authentication
/// </summary>
public bool IsPreAuthRequired { get { return false; } }
#pragma warning disable 0067
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationFailedDelegate OnAuthenticationFailed;
#pragma warning restore 0067
private string _credentials;
public HeaderAuthenticator(string credentials)
{
this._credentials = credentials;
}
/// <summary>
/// Not used as IsPreAuthRequired is false
/// </summary>
public void StartAuthentication()
{ }
/// <summary>
/// Prepares the request by adding two headers to it
/// </summary>
public void PrepareRequest(BestHTTP.HTTPRequest request)
{
#if !UNITY_WEBGL || UNITY_EDITOR
request.SetHeader("Authorization", "Bearer " + this._credentials);
#endif
}
public Uri PrepareUri(Uri uri)
{
#if UNITY_WEBGL && !UNITY_EDITOR
string query = string.IsNullOrEmpty(uri.Query) ? "?" : uri.Query + "&";
UriBuilder uriBuilder = new UriBuilder(uri.Scheme, uri.Host, uri.Port, uri.AbsolutePath, query + "access_token=" + this._credentials);
return uriBuilder.Uri;
#else
return uri;
#endif
}
public void Cancel()
{
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/Authentication Providers/HeaderAuthenticator.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80b2246c164414c468eea4f0550eb9ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d7347b3e5f014ce4b8ac59f9ac94f7c8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

37
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/JsonDotNetEncoder.cs

@ -0,0 +1,37 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE && BESTHTTP_SIGNALR_CORE_ENABLE_NEWTONSOFT_JSON_DOTNET_ENCODER
using System;
using BestHTTP.PlatformSupport.Memory;
namespace BestHTTP.SignalRCore.Encoders
{
public sealed class JsonDotNetEncoder : BestHTTP.SignalRCore.IEncoder
{
public object ConvertTo(Type toType, object obj)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
return Newtonsoft.Json.JsonConvert.DeserializeObject(json, toType);
}
public T DecodeAs<T>(BufferSegment buffer)
{
using (var reader = new System.IO.StreamReader(new System.IO.MemoryStream(buffer.Data, buffer.Offset, buffer.Count)))
using (var jsonReader = new Newtonsoft.Json.JsonTextReader(reader))
return new Newtonsoft.Json.JsonSerializer().Deserialize<T>(jsonReader);
}
public BufferSegment Encode<T>(T value)
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(value);
int len = System.Text.Encoding.UTF8.GetByteCount(json);
byte[] buffer = BufferPool.Get(len + 1, true);
System.Text.Encoding.UTF8.GetBytes(json, 0, json.Length, buffer, 0);
buffer[len] = 0x1e;
return new BufferSegment(buffer, 0, len + 1);
}
}
}
#endif

13
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/JsonDotNetEncoder.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5e565b09f1e97ee4c9d119735901397b
timeCreated: 1515401618
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

47
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/LitJsonEncoder.cs

@ -0,0 +1,47 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using System;
using BestHTTP.PlatformSupport.Memory;
using BestHTTP.JSON.LitJson;
namespace BestHTTP.SignalRCore.Encoders
{
public sealed class LitJsonEncoder : BestHTTP.SignalRCore.IEncoder
{
public LitJsonEncoder()
{
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<int, long>((input) => input);
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<long, int>((input) => (int)input);
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<double, int>((input) => (int)(input + 0.5));
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<string, DateTime>((input) => Convert.ToDateTime((string)input).ToUniversalTime());
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<double, float>((input) => (float)input);
BestHTTP.JSON.LitJson.JsonMapper.RegisterImporter<string, byte[]>((input) => Convert.FromBase64String(input));
BestHTTP.JSON.LitJson.JsonMapper.RegisterExporter<float>((f, writer) => writer.Write((double)f));
}
public T DecodeAs<T>(BufferSegment buffer)
{
using (var reader = new System.IO.StreamReader(new System.IO.MemoryStream(buffer.Data, buffer.Offset, buffer.Count)))
{
return JsonMapper.ToObject<T>(reader);
}
}
public PlatformSupport.Memory.BufferSegment Encode<T>(T value)
{
var json = JsonMapper.ToJson(value);
int len = System.Text.Encoding.UTF8.GetByteCount(json);
byte[] buffer = BufferPool.Get(len + 1, true);
System.Text.Encoding.UTF8.GetBytes(json, 0, json.Length, buffer, 0);
buffer[len] = (byte)JsonProtocol.Separator;
return new BufferSegment(buffer, 0, len + 1);
}
public object ConvertTo(Type toType, object obj)
{
string json = BestHTTP.JSON.LitJson.JsonMapper.ToJson(obj);
return BestHTTP.JSON.LitJson.JsonMapper.ToObject(toType, json);
}
}
}
#endif

13
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/LitJsonEncoder.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b5784b64da7c8ad47b441a9f2f27a33b
timeCreated: 1515401618
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

567
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackCSharpProtocol.cs

@ -0,0 +1,567 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE && BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
using System;
using System.Buffers;
using System.Collections.Generic;
using BestHTTP.Extensions;
using BestHTTP.PlatformSupport.Memory;
using BestHTTP.SignalRCore.Messages;
using MessagePack;
namespace BestHTTP.SignalRCore.Encoders
{
class BufferPoolBufferWriter : IBufferWriter<byte>
{
private BufferPoolMemoryStream underlyingStream;
private BufferSegment last;
public BufferPoolBufferWriter(BufferPoolMemoryStream stream)
{
this.underlyingStream = stream;
this.last = BufferSegment.Empty;
}
public void Advance(int count)
{
this.underlyingStream.Write(this.last.Data, this.last.Offset, this.last.Count + count);
BufferPool.Release(this.last);
this.last = BufferSegment.Empty;
}
public Memory<byte> GetMemory(int sizeHint = 0)
{
var buffer = BufferPool.Get(Math.Max(sizeHint, BufferPool.MinBufferSize), true);
//Array.Clear(buffer, 0, buffer.Length);
this.last = new BufferSegment(buffer, 0, 0);
return new Memory<byte>(buffer, 0, buffer.Length);
}
public Span<byte> GetSpan(int sizeHint = 0)
{
var buffer = BufferPool.Get(Math.Max(sizeHint, BufferPool.MinBufferSize), true);
//Array.Clear(buffer, 0, buffer.Length);
this.last = new BufferSegment(buffer, 0, 0);
return new Span<byte>(buffer, 0, buffer.Length);
}
}
public sealed class MessagePackCSharpProtocol : BestHTTP.SignalRCore.IProtocol
{
public string Name { get { return "messagepack"; } }
public TransferModes Type { get { return TransferModes.Binary; } }
public IEncoder Encoder { get; private set; }
public HubConnection Connection { get; set; }
public BufferSegment EncodeMessage(Message message)
{
var memBuffer = BufferPool.Get(256, true);
var stream = new BufferPoolMemoryStream(memBuffer, 0, memBuffer.Length, true, true, false, true);
// Write 5 bytes for placeholder for length prefix
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
var bufferWriter = new BufferPoolBufferWriter(stream);
var writer = new MessagePackWriter(bufferWriter);
switch (message.type)
{
case MessageTypes.StreamItem:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1
// [2, Headers, InvocationId, Item]
writer.WriteArrayHeader(4);
writer.Write(2);
WriteHeaders(ref writer);
WriteString(ref writer, message.invocationId);
WriteValue(ref writer, bufferWriter, message.item);
break;
case MessageTypes.Completion:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1
// [3, Headers, InvocationId, ResultKind, Result?]
byte resultKind = (byte)(!string.IsNullOrEmpty(message.error) ? /*error*/ 1 : message.result != null ? /*non-void*/ 3 : /*void*/ 2);
writer.WriteArrayHeader(resultKind == 2 ? 4 : 5);
writer.Write(3);
WriteHeaders(ref writer);
WriteString(ref writer, message.invocationId);
writer.Write(resultKind);
if (resultKind == 1) // error
WriteString(ref writer, message.error);
else if (resultKind == 3) // non-void
WriteValue(ref writer, bufferWriter, message.result);
break;
case MessageTypes.Invocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1
// [1, Headers, InvocationId, NonBlocking, Target, [Arguments], [StreamIds]]
case MessageTypes.StreamInvocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1
// [4, Headers, InvocationId, Target, [Arguments], [StreamIds]]
writer.WriteArrayHeader(message.streamIds != null ? 6 : 5);
writer.Write((int)message.type);
WriteHeaders(ref writer);
WriteString(ref writer, message.invocationId);
WriteString(ref writer, message.target);
writer.WriteArrayHeader(message.arguments != null ? message.arguments.Length : 0);
if (message.arguments != null)
for (int i = 0; i < message.arguments.Length; ++i)
WriteValue(ref writer, bufferWriter, message.arguments[i]);
if (message.streamIds != null)
{
writer.WriteArrayHeader(message.streamIds.Length);
for (int i = 0; i < message.streamIds.Length; ++i)
WriteValue(ref writer, bufferWriter, message.streamIds[i]);
}
break;
case MessageTypes.CancelInvocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1
// [5, Headers, InvocationId]
writer.WriteArrayHeader(3);
writer.Write(5);
WriteHeaders(ref writer);
WriteString(ref writer, message.invocationId);
break;
case MessageTypes.Ping:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
// [6]
writer.WriteArrayHeader(1);
writer.Write(6);
break;
case MessageTypes.Close:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1
// [7, Error, AllowReconnect?]
writer.WriteArrayHeader(string.IsNullOrEmpty(message.error) ? 1 : 2);
writer.Write(7);
if (!string.IsNullOrEmpty(message.error))
WriteString(ref writer, message.error);
break;
}
writer.Flush();
// get how much bytes got written to the buffer. This includes the 5 placeholder bytes too.
int length = (int)stream.Position;
// this is the length without the 5 placeholder bytes
int contentLength = length - 5;
// get the stream's internal buffer. We set the releaseBuffer flag to false, so we can use it safely.
var buffer = stream.GetBuffer();
// add varint length prefix
byte prefixBytes = GetRequiredBytesForLengthPrefix(contentLength);
WriteLengthAsVarInt(buffer, 5 - prefixBytes, contentLength);
// return with the final segment
return new BufferSegment(buffer, 5 - prefixBytes, contentLength + prefixBytes);
}
private void WriteValue(ref MessagePackWriter writer, BufferPoolBufferWriter bufferWriter, object item)
{
if (item == null)
writer.WriteNil();
else
{
writer.Flush();
MessagePackSerializer.Serialize(item.GetType(), bufferWriter, item);
}
}
private void WriteString(ref MessagePackWriter writer, string str)
{
if (str == null)
writer.WriteNil();
else
{
int count = System.Text.Encoding.UTF8.GetByteCount(str);
var buffer = BufferPool.Get(count, true);
System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buffer, 0);
writer.WriteString(new ReadOnlySpan<byte>(buffer, 0, count));
BufferPool.Release(buffer);
}
}
private void WriteHeaders(ref MessagePackWriter writer)
{
writer.WriteMapHeader(0);
}
public void ParseMessages(BufferSegment segment, ref List<Message> messages)
{
int offset = segment.Offset;
while (offset < segment.Count)
{
int length = (int)ReadVarInt(segment.Data, ref offset);
var reader = new MessagePackReader(new ReadOnlyMemory<byte>(segment.Data, offset, length));
int arrayLength = reader.ReadArrayHeader();
int messageType = reader.ReadByte();
switch ((MessageTypes)messageType)
{
case MessageTypes.Invocation: messages.Add(ReadInvocation(ref reader)); break;
case MessageTypes.StreamItem: messages.Add(ReadStreamItem(ref reader)); break;
case MessageTypes.Completion: messages.Add(ReadCompletion(ref reader)); break;
case MessageTypes.StreamInvocation: messages.Add(ReadStreamInvocation(ref reader)); break;
case MessageTypes.CancelInvocation: messages.Add(ReadCancelInvocation(ref reader)); break;
case MessageTypes.Ping:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
messages.Add(new Message { type = MessageTypes.Ping });
break;
case MessageTypes.Close: messages.Add(ReadClose(ref reader)); break;
}
offset += length;
}
}
private Message ReadClose(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1
string error = reader.ReadString();
bool allowReconnect = false;
try
{
allowReconnect = reader.ReadBoolean();
}
catch { }
return new Message
{
type = MessageTypes.Close,
error = error,
allowReconnect = allowReconnect
};
}
private Message ReadCancelInvocation(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1
ReadHeaders(ref reader);
string invocationId = reader.ReadString();
return new Message
{
type = MessageTypes.CancelInvocation,
invocationId = invocationId
};
}
private Message ReadStreamInvocation(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1
ReadHeaders(ref reader);
string invocationId = reader.ReadString();
string target = reader.ReadString();
object[] arguments = ReadArguments(ref reader, target);
string[] streamIds = ReadStreamIds(ref reader);
return new Message
{
type = MessageTypes.StreamInvocation,
invocationId = invocationId,
target = target,
arguments = arguments,
streamIds = streamIds
};
}
private Message ReadCompletion(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1
ReadHeaders(ref reader);
string invocationId = reader.ReadString();
byte resultKind = reader.ReadByte();
switch (resultKind)
{
// 1 - Error result - Result contains a String with the error message
case 1:
string error = reader.ReadString();
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId,
error = error
};
// 2 - Void result - Result is absent
case 2:
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId
};
// 3 - Non-Void result - Result contains the value returned by the server
case 3:
object item = ReadItem(ref reader, invocationId);
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId,
item = item,
result = item
};
default:
throw new NotImplementedException("Unknown resultKind: " + resultKind);
}
}
private Message ReadStreamItem(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1
ReadHeaders(ref reader);
string invocationId = reader.ReadString();
object item = ReadItem(ref reader, invocationId);
return new Message
{
type = MessageTypes.StreamItem,
invocationId = invocationId,
item = item
};
}
private Message ReadInvocation(ref MessagePackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1
ReadHeaders(ref reader);
string invocationId = reader.ReadString();
string target = reader.ReadString();
object[] arguments = ReadArguments(ref reader, target);
string[] streamIds = ReadStreamIds(ref reader);
return new Message
{
type = MessageTypes.Invocation,
invocationId = invocationId,
target = target,
arguments = arguments,
streamIds = streamIds
};
}
private object ReadItem(ref MessagePackReader reader, string invocationId)
{
long longId = 0;
if (long.TryParse(invocationId, out longId))
{
Type itemType = this.Connection.GetItemType(longId);
return MessagePackSerializer.Deserialize(itemType, reader.ReadRaw());
}
else
{
reader.Skip();
return null;
}
}
private string[] ReadStreamIds(ref MessagePackReader reader)
{
var count = reader.ReadArrayHeader();
string[] result = null;
if (count > 0)
{
result = new string[count];
for (int i = 0; i < count; i++)
result[i] = reader.ReadString();
}
return result;
}
private object[] ReadArguments(ref MessagePackReader reader, string target)
{
var subscription = this.Connection.GetSubscription(target);
object[] args = null;
if (subscription == null || subscription.callbacks == null || subscription.callbacks.Count == 0)
{
reader.Skip();
}
else
{
int count = reader.ReadArrayHeader();
if (subscription.callbacks[0].ParamTypes != null)
{
args = new object[subscription.callbacks[0].ParamTypes.Length];
for (int i = 0; i < subscription.callbacks[0].ParamTypes.Length; ++i)
args[i] = MessagePackSerializer.Deserialize(subscription.callbacks[0].ParamTypes[i], reader.ReadRaw());
}
else
args = null;
}
return args;
}
private Dictionary<string, string> ReadHeaders(ref MessagePackReader reader)
{
int count = reader.ReadMapHeader();
Dictionary<string, string> result = null;
if (count > 0)
{
result = new Dictionary<string, string>(count);
for (int i = 0; i < count; i++)
{
string key = reader.ReadString();
string value = reader.ReadString();
result.Add(key, value);
}
}
return result;
}
public static byte GetRequiredBytesForLengthPrefix(int length)
{
byte bytes = 0;
do
{
length >>= 7;
bytes++;
}
while (length > 0);
return bytes;
}
public static int WriteLengthAsVarInt(byte[] data, int offset, int length)
{
do
{
var current = data[offset];
current = (byte)(length & 0x7f);
length >>= 7;
if (length > 0)
{
current |= 0x80;
}
data[offset++] = current;
}
while (length > 0);
return offset;
}
public static uint ReadVarInt(byte[] data, ref int offset)
{
var length = 0U;
var numBytes = 0;
byte byteRead;
do
{
byteRead = data[offset + numBytes];
length = length | (((uint)(byteRead & 0x7f)) << (numBytes * 7));
numBytes++;
}
while (offset + numBytes < data.Length && ((byteRead & 0x80) != 0));
offset += numBytes;
return length;
}
public object ConvertTo(Type toType, object obj)
{
if (obj == null)
return null;
#if NETFX_CORE
TypeInfo typeInfo = toType.GetTypeInfo();
#endif
#if NETFX_CORE
if (typeInfo.IsEnum)
#else
if (toType.IsEnum)
#endif
return Enum.Parse(toType, obj.ToString(), true);
#if NETFX_CORE
if (typeInfo.IsPrimitive)
#else
if (toType.IsPrimitive)
#endif
return Convert.ChangeType(obj, toType);
if (toType == typeof(string))
return obj.ToString();
#if NETFX_CORE
if (typeInfo.IsGenericType && toType.Name == "Nullable`1")
return Convert.ChangeType(obj, toType.GenericTypeArguments[0]);
#else
if (toType.IsGenericType && toType.Name == "Nullable`1")
return Convert.ChangeType(obj, toType.GetGenericArguments()[0]);
#endif
return obj;
}
public object[] GetRealArguments(Type[] argTypes, object[] arguments)
{
if (arguments == null || arguments.Length == 0)
return null;
if (argTypes.Length > arguments.Length)
throw new Exception(string.Format("argType.Length({0}) < arguments.length({1})", argTypes.Length, arguments.Length));
return arguments;
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackCSharpProtocol.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c4d3d400dd496d43a409e350143e85a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

868
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackProtocol.cs

@ -0,0 +1,868 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE && BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
using System;
using System.Collections.Generic;
using BestHTTP.PlatformSupport.Memory;
using BestHTTP.SignalRCore.Messages;
using GameDevWare.Serialization;
using GameDevWare.Serialization.MessagePack;
using GameDevWare.Serialization.Serializers;
using UnityEngine;
namespace BestHTTP.SignalRCore.Encoders
{
public sealed class MessagePackProtocolSerializationOptions
{
/// <summary>
/// A function that must return a TypeSerializer for the given Type. To serialize an enum it can return an EnumNumberSerializer (default) to serialize enums as numbers or EnumSerializer to serialize them as strings.
/// </summary>
public Func<Type, TypeSerializer> EnumSerializerFactory;
}
/// <summary>
/// IPRotocol implementation using the "Json & MessagePack Serialization" asset store package (https://assetstore.unity.com/packages/tools/network/json-messagepack-serialization-59918).
/// </summary>
public sealed class MessagePackProtocol : BestHTTP.SignalRCore.IProtocol
{
public string Name { get { return "messagepack"; } }
public TransferModes Type { get { return TransferModes.Binary; } }
public IEncoder Encoder { get; private set; }
public HubConnection Connection { get; set; }
public MessagePackProtocolSerializationOptions Options { get; set; }
public MessagePackProtocol()
: this(new MessagePackProtocolSerializationOptions { EnumSerializerFactory = (enumType) => new EnumNumberSerializer(enumType) })
{
}
public MessagePackProtocol(MessagePackProtocolSerializationOptions options)
{
this.Options = options;
GameDevWare.Serialization.Json.DefaultSerializers.Clear();
GameDevWare.Serialization.Json.DefaultSerializers.AddRange(new TypeSerializer[]
{
new BinarySerializer(),
new DateTimeOffsetSerializer(),
new DateTimeSerializer(),
new GuidSerializer(),
new StreamSerializer(),
new UriSerializer(),
new VersionSerializer(),
new TimeSpanSerializer(),
new DictionaryEntrySerializer(),
new BestHTTP.SignalRCore.Encoders.Vector2Serializer(),
new BestHTTP.SignalRCore.Encoders.Vector3Serializer(),
new BestHTTP.SignalRCore.Encoders.Vector4Serializer(),
new PrimitiveSerializer(typeof (bool)),
new PrimitiveSerializer(typeof (byte)),
new PrimitiveSerializer(typeof (decimal)),
new PrimitiveSerializer(typeof (double)),
new PrimitiveSerializer(typeof (short)),
new PrimitiveSerializer(typeof (int)),
new PrimitiveSerializer(typeof (long)),
new PrimitiveSerializer(typeof (sbyte)),
new PrimitiveSerializer(typeof (float)),
new PrimitiveSerializer(typeof (ushort)),
new PrimitiveSerializer(typeof (uint)),
new PrimitiveSerializer(typeof (ulong)),
new PrimitiveSerializer(typeof (string)),
});
}
/// <summary>
/// This function must convert all element in the arguments array to the corresponding type from the argTypes array.
/// </summary>
public object[] GetRealArguments(Type[] argTypes, object[] arguments)
{
if (arguments == null || arguments.Length == 0)
return null;
if (argTypes.Length > arguments.Length)
throw new Exception(string.Format("argType.Length({0}) < arguments.length({1})", argTypes.Length, arguments.Length));
return arguments;
}
/// <summary>
/// Convert a value to the given type.
/// </summary>
public object ConvertTo(Type toType, object obj)
{
if (obj == null)
return null;
#if NETFX_CORE
TypeInfo typeInfo = toType.GetTypeInfo();
#endif
#if NETFX_CORE
if (typeInfo.IsEnum)
#else
if (toType.IsEnum)
#endif
return Enum.Parse(toType, obj.ToString(), true);
#if NETFX_CORE
if (typeInfo.IsPrimitive)
#else
if (toType.IsPrimitive)
#endif
return Convert.ChangeType(obj, toType);
if (toType == typeof(string))
return obj.ToString();
#if NETFX_CORE
if (typeInfo.IsGenericType && toType.Name == "Nullable`1")
return Convert.ChangeType(obj, toType.GenericTypeArguments[0]);
#else
if (toType.IsGenericType && toType.Name == "Nullable`1")
return Convert.ChangeType(obj, toType.GetGenericArguments()[0]);
#endif
return obj;
}
/// <summary>
/// This function must return the encoded representation of the given message.
/// </summary>
public BufferSegment EncodeMessage(Message message)
{
var memBuffer = BufferPool.Get(256, true);
var stream = new BestHTTP.Extensions.BufferPoolMemoryStream(memBuffer, 0, memBuffer.Length, true, true, false, true);
// Write 5 bytes for placeholder for length prefix
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
stream.WriteByte(0);
var buffer = BufferPool.Get(MsgPackWriter.DEFAULT_BUFFER_SIZE, true);
var context = new SerializationContext {
Options = SerializationOptions.SuppressTypeInformation,
EnumSerializerFactory = this.Options.EnumSerializerFactory,
ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance
};
var writer = new MsgPackWriter(stream, context, buffer);
switch (message.type)
{
case MessageTypes.StreamItem:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1
// [2, Headers, InvocationId, Item]
writer.WriteArrayBegin(4);
writer.WriteNumber(2);
WriteHeaders(writer);
writer.WriteString(message.invocationId);
WriteValue(writer, message.item);
writer.WriteArrayEnd();
break;
case MessageTypes.Completion:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1
// [3, Headers, InvocationId, ResultKind, Result?]
byte resultKind = (byte)(!string.IsNullOrEmpty(message.error) ? /*error*/ 1 : message.result != null ? /*non-void*/ 3 : /*void*/ 2);
writer.WriteArrayBegin(resultKind == 2 ? 4 : 5);
writer.WriteNumber(3);
WriteHeaders(writer);
writer.WriteString(message.invocationId);
writer.WriteNumber(resultKind);
if (resultKind == 1) // error
writer.WriteString(message.error);
else if (resultKind == 3) // non-void
WriteValue(writer, message.result);
writer.WriteArrayEnd();
break;
case MessageTypes.Invocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1
// [1, Headers, InvocationId, NonBlocking, Target, [Arguments], [StreamIds]]
case MessageTypes.StreamInvocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1
// [4, Headers, InvocationId, Target, [Arguments], [StreamIds]]
writer.WriteArrayBegin(message.streamIds != null ? 6 : 5);
writer.WriteNumber((int)message.type);
WriteHeaders(writer);
writer.WriteString(message.invocationId);
writer.WriteString(message.target);
writer.WriteArrayBegin(message.arguments != null ? message.arguments.Length : 0);
if (message.arguments != null)
for (int i = 0; i < message.arguments.Length; ++i)
WriteValue(writer, message.arguments[i]);
writer.WriteArrayEnd();
if (message.streamIds != null)
{
writer.WriteArrayBegin(message.streamIds.Length);
for (int i = 0; i < message.streamIds.Length; ++i)
WriteValue(writer, message.streamIds[i]);
writer.WriteArrayEnd();
}
writer.WriteArrayEnd();
break;
case MessageTypes.CancelInvocation:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1
// [5, Headers, InvocationId]
writer.WriteArrayBegin(3);
writer.WriteNumber(5);
WriteHeaders(writer);
writer.WriteString(message.invocationId);
writer.WriteArrayEnd();
break;
case MessageTypes.Ping:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
// [6]
writer.WriteArrayBegin(1);
writer.WriteNumber(6);
writer.WriteArrayEnd();
break;
case MessageTypes.Close:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1
// [7, Error, AllowReconnect?]
writer.WriteArrayBegin(string.IsNullOrEmpty(message.error) ? 1 : 2);
writer.WriteNumber(7);
if (!string.IsNullOrEmpty(message.error))
writer.WriteString(message.error);
writer.WriteArrayEnd();
break;
}
writer.Flush();
// release back the buffer we used for the MsgPackWriter
BufferPool.Release(buffer);
// get how much bytes got written to the buffer. This includes the 5 placeholder bytes too.
int length = (int)stream.Position;
// this is the length without the 5 placeholder bytes
int contentLength = length - 5;
// get the stream's internal buffer. We set the releaseBuffer flag to false, so we can use it safely.
buffer = stream.GetBuffer();
// add varint length prefix
byte prefixBytes = GetRequiredBytesForLengthPrefix(contentLength);
WriteLengthAsVarInt(buffer, 5 - prefixBytes, contentLength);
// return with the final segment
return new BufferSegment(buffer, 5 - prefixBytes, contentLength + prefixBytes);
}
private void WriteValue(MsgPackWriter writer, object value)
{
if (value == null)
writer.WriteNull();
else
writer.WriteValue(value, value.GetType());
}
private void WriteHeaders(MsgPackWriter writer)
{
writer.WriteObjectBegin(0);
writer.WriteObjectEnd();
}
/// <summary>
/// This function must parse binary representation of the messages into the list of Messages.
/// </summary>
public void ParseMessages(BufferSegment segment, ref List<Message> messages)
{
messages.Clear();
int offset = segment.Offset;
while (offset < segment.Count)
{
int length = (int)ReadVarInt(segment.Data, ref offset);
using (var stream = new System.IO.MemoryStream(segment.Data, offset, length))
{
var buff = BufferPool.Get(MsgPackReader.DEFAULT_BUFFER_SIZE, true);
try
{
var context = new SerializationContext {
Options = SerializationOptions.SuppressTypeInformation,
ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance
};
var reader = new MsgPackReader(stream, context, Endianness.BigEndian, buff);
reader.NextToken();
reader.NextToken();
int messageType = reader.ReadByte();
switch ((MessageTypes)messageType)
{
case MessageTypes.Invocation: messages.Add(ReadInvocation(reader)); break;
case MessageTypes.StreamItem: messages.Add(ReadStreamItem(reader)); break;
case MessageTypes.Completion: messages.Add(ReadCompletion(reader)); break;
case MessageTypes.StreamInvocation: messages.Add(ReadStreamInvocation(reader)); break;
case MessageTypes.CancelInvocation: messages.Add(ReadCancelInvocation(reader)); break;
case MessageTypes.Ping:
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
messages.Add(new Message { type = MessageTypes.Ping });
break;
case MessageTypes.Close: messages.Add(ReadClose(reader)); break;
}
reader.NextToken();
}
finally
{
BufferPool.Release(buff);
}
}
offset += length;
}
}
private Message ReadClose(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1
string error = reader.ReadString();
bool allowReconnect = false;
try
{
allowReconnect = reader.ReadBoolean();
}
catch { }
return new Message
{
type = MessageTypes.Close,
error = error,
allowReconnect = allowReconnect
};
}
private Message ReadCancelInvocation(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1
ReadHeaders(reader);
string invocationId = reader.ReadString();
return new Message
{
type = MessageTypes.CancelInvocation,
invocationId = invocationId
};
}
private Message ReadStreamInvocation(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1
ReadHeaders(reader);
string invocationId = reader.ReadString();
string target = reader.ReadString();
object[] arguments = ReadArguments(reader, target);
string[] streamIds = ReadStreamIds(reader);
return new Message
{
type = MessageTypes.StreamInvocation,
invocationId = invocationId,
target = target,
arguments = arguments,
streamIds = streamIds
};
}
private Message ReadCompletion(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1
ReadHeaders(reader);
string invocationId = reader.ReadString();
byte resultKind = reader.ReadByte();
switch(resultKind)
{
// 1 - Error result - Result contains a String with the error message
case 1:
string error = reader.ReadString();
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId,
error = error
};
// 2 - Void result - Result is absent
case 2:
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId
};
// 3 - Non-Void result - Result contains the value returned by the server
case 3:
object item = ReadItem(reader, invocationId);
return new Message
{
type = MessageTypes.Completion,
invocationId = invocationId,
item = item,
result = item
};
default:
throw new NotImplementedException("Unknown resultKind: " + resultKind);
}
}
private Message ReadStreamItem(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1
ReadHeaders(reader);
string invocationId = reader.ReadString();
object item = ReadItem(reader, invocationId);
return new Message
{
type = MessageTypes.StreamItem,
invocationId = invocationId,
item = item
};
}
private Message ReadInvocation(MsgPackReader reader)
{
// https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1
ReadHeaders(reader);
string invocationId = reader.ReadString();
string target = reader.ReadString();
object[] arguments = ReadArguments(reader, target);
string[] streamIds = ReadStreamIds(reader);
return new Message
{
type = MessageTypes.Invocation,
invocationId = invocationId,
target = target,
arguments = arguments,
streamIds = streamIds
};
}
private object ReadItem(MsgPackReader reader, string invocationId)
{
long longId = 0;
if (long.TryParse(invocationId, out longId))
{
Type itemType = this.Connection.GetItemType(longId);
return reader.ReadValue(itemType);
}
else
return reader.ReadValue(typeof(object));
}
private string[] ReadStreamIds(MsgPackReader reader)
{
return reader.ReadValue(typeof(string[])) as string[];
}
private object[] ReadArguments(MsgPackReader reader, string target)
{
var subscription = this.Connection.GetSubscription(target);
object[] args;
if (subscription == null || subscription.callbacks == null || subscription.callbacks.Count == 0)
{
args = reader.ReadValue(typeof(object[])) as object[];
}
else
{
reader.NextToken();
if (subscription.callbacks[0].ParamTypes != null)
{
args = new object[subscription.callbacks[0].ParamTypes.Length];
for (int i = 0; i < subscription.callbacks[0].ParamTypes.Length; ++i)
args[i] = reader.ReadValue(subscription.callbacks[0].ParamTypes[i]);
}
else
args = null;
reader.NextToken();
}
return args;
}
private Dictionary<string, string> ReadHeaders(MsgPackReader reader)
{
return reader.ReadValue(typeof(Dictionary<string, string>)) as Dictionary<string, string>;
}
public static byte GetRequiredBytesForLengthPrefix(int length)
{
byte bytes = 0;
do
{
length >>= 7;
bytes++;
}
while (length > 0);
return bytes;
}
public static int WriteLengthAsVarInt(byte[] data, int offset, int length)
{
do
{
var current = data[offset];
current = (byte)(length & 0x7f);
length >>= 7;
if (length > 0)
{
current |= 0x80;
}
data[offset++] = current;
}
while (length > 0);
return offset;
}
public static uint ReadVarInt(byte[] data, ref int offset)
{
var length = 0U;
var numBytes = 0;
byte byteRead;
do
{
byteRead = data[offset + numBytes];
length = length | (((uint)(byteRead & 0x7f)) << (numBytes * 7));
numBytes++;
}
while (offset + numBytes < data.Length && ((byteRead & 0x80) != 0));
offset += numBytes;
return length;
}
}
public sealed class CustomMessagePackExtensionTypeHandler : MessagePackExtensionTypeHandler
{
public const int EXTENSION_TYPE_DATE_TIME = -1;
public const int DATE_TIME_SIZE = 8;
public const long BclSecondsAtUnixEpoch = 62135596800;
public const int NanosecondsPerTick = 100;
public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static readonly Type[] DefaultExtensionTypes = new[] { typeof(DateTime) };
public static CustomMessagePackExtensionTypeHandler Instance = new CustomMessagePackExtensionTypeHandler();
public override IEnumerable<Type> ExtensionTypes
{
get { return DefaultExtensionTypes; }
}
public override bool TryRead(sbyte type, ArraySegment<byte> data, out object value)
{
if (data.Array == null) throw new ArgumentNullException("data");
value = default(object);
switch (type)
{
case EXTENSION_TYPE_DATE_TIME:
switch (data.Count)
{
case 4:
{
var intValue = unchecked((int)(FromBytes(data.Array, data.Offset, 4)));
value = CustomMessagePackExtensionTypeHandler.UnixEpoch.AddSeconds(unchecked((uint)intValue));
return true;
}
case 8:
{
long longValue = FromBytes(data.Array, data.Offset, 8);
ulong ulongValue = unchecked((ulong)longValue);
long nanoseconds = (long)(ulongValue >> 34);
ulong seconds = ulongValue & 0x00000003ffffffffL;
value = CustomMessagePackExtensionTypeHandler.UnixEpoch.AddSeconds(seconds).AddTicks(nanoseconds / CustomMessagePackExtensionTypeHandler.NanosecondsPerTick);
return true;
}
case 12:
{
var intValue = unchecked((int)(FromBytes(data.Array, data.Offset, 4)));
long longValue = FromBytes(data.Array, data.Offset, 8);
var nanoseconds = unchecked((uint)intValue);
value = CustomMessagePackExtensionTypeHandler.UnixEpoch.AddSeconds(longValue).AddTicks(nanoseconds / CustomMessagePackExtensionTypeHandler.NanosecondsPerTick);
return true;
}
default:
throw new Exception($"Length of extension was {data.Count}. Either 4, 8 or 12 were expected.");
}
default:
return false;
}
}
public override bool TryWrite(object value, out sbyte type, ref ArraySegment<byte> data)
{
if (value == null)
{
type = 0;
return false;
}
else if (value is DateTime)
{
type = EXTENSION_TYPE_DATE_TIME;
var dateTime = (DateTime)(object)value;
// The spec requires UTC. Convert to UTC if we're sure the value was expressed as Local time.
// If it's Unspecified, we want to leave it alone since .NET will change the value when we convert
// and we simply don't know, so we should leave it as-is.
if (dateTime.Kind == DateTimeKind.Local)
{
dateTime = dateTime.ToUniversalTime();
}
var secondsSinceBclEpoch = dateTime.Ticks / TimeSpan.TicksPerSecond;
var seconds = secondsSinceBclEpoch - CustomMessagePackExtensionTypeHandler.BclSecondsAtUnixEpoch;
var nanoseconds = (dateTime.Ticks % TimeSpan.TicksPerSecond) * CustomMessagePackExtensionTypeHandler.NanosecondsPerTick;
if ((seconds >> 34) == 0)
{
var data64 = unchecked((ulong)((nanoseconds << 34) | seconds));
if ((data64 & 0xffffffff00000000L) == 0)
{
// timestamp 32(seconds in 32-bit unsigned int)
var data32 = (UInt32)data64;
const int TIMESTAMP_SIZE = 4;
if (data.Array == null || data.Count < TIMESTAMP_SIZE)
data = new ArraySegment<byte>(new byte[TIMESTAMP_SIZE]);
CopyBytesImpl(data32, 4, data.Array, data.Offset);
if (data.Count != DATE_TIME_SIZE)
data = new ArraySegment<byte>(data.Array, data.Offset, DATE_TIME_SIZE);
}
else
{
// timestamp 64(nanoseconds in 30-bit unsigned int | seconds in 34-bit unsigned int)
const int TIMESTAMP_SIZE = 8;
if (data.Array == null || data.Count < TIMESTAMP_SIZE)
data = new ArraySegment<byte>(new byte[TIMESTAMP_SIZE]);
CopyBytesImpl(unchecked((long)data64), 8, data.Array, data.Offset);
if (data.Count != DATE_TIME_SIZE)
data = new ArraySegment<byte>(data.Array, data.Offset, DATE_TIME_SIZE);
}
}
else
{
// timestamp 96( nanoseconds in 32-bit unsigned int | seconds in 64-bit signed int )
const int TIMESTAMP_SIZE = 12;
if (data.Array == null || data.Count < TIMESTAMP_SIZE)
data = new ArraySegment<byte>(new byte[TIMESTAMP_SIZE]);
CopyBytesImpl((uint)nanoseconds, 4, data.Array, data.Offset);
CopyBytesImpl(seconds, 8, data.Array, data.Offset + 4);
if (data.Count != DATE_TIME_SIZE)
data = new ArraySegment<byte>(data.Array, data.Offset, DATE_TIME_SIZE);
}
return true;
}
type = default(sbyte);
return false;
}
private void CopyBytesImpl(long value, int bytes, byte[] buffer, int index)
{
var endOffset = index + bytes - 1;
for (var i = 0; i < bytes; i++)
{
buffer[endOffset - i] = unchecked((byte)(value & 0xff));
value = value >> 8;
}
}
private long FromBytes(byte[] buffer, int startIndex, int bytesToConvert)
{
long ret = 0;
for (var i = 0; i < bytesToConvert; i++)
{
ret = unchecked((ret << 8) | buffer[startIndex + i]);
}
return ret;
}
}
// https://github.com/neuecc/MessagePack-CSharp/blob/13c299a5172c60154bae53395612af194c02d286/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Unity/Formatters.cs#L15
public sealed class Vector2Serializer : TypeSerializer
{
public override Type SerializedType { get { return typeof(Vector2); } }
public override object Deserialize(IJsonReader reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (reader.Token == JsonToken.Null)
return null;
var value = new Vector2();
reader.ReadArrayBegin();
int idx = 0;
while (reader.Token != JsonToken.EndOfArray)
value[idx++] = reader.ReadSingle();
reader.ReadArrayEnd(nextToken: false);
return value;
}
public override void Serialize(IJsonWriter writer, object value)
{
if (writer == null) throw new ArgumentNullException("writer");
if (value == null) throw new ArgumentNullException("value");
var vector2 = (Vector2)value;
writer.WriteArrayBegin(2);
writer.Write(vector2.x);
writer.Write(vector2.y);
writer.WriteArrayEnd();
}
}
// https://github.com/neuecc/MessagePack-CSharp/blob/13c299a5172c60154bae53395612af194c02d286/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Unity/Formatters.cs#L56
public sealed class Vector3Serializer : TypeSerializer
{
public override Type SerializedType { get { return typeof(Vector3); } }
public override object Deserialize(IJsonReader reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (reader.Token == JsonToken.Null)
return null;
var value = new Vector3();
reader.ReadArrayBegin();
int idx = 0;
while (reader.Token != JsonToken.EndOfArray)
value[idx++] = reader.ReadSingle();
reader.ReadArrayEnd(nextToken: false);
return value;
}
public override void Serialize(IJsonWriter writer, object value)
{
if (writer == null) throw new ArgumentNullException("writer");
if (value == null) throw new ArgumentNullException("value");
var vector3 = (Vector3)value;
writer.WriteArrayBegin(3);
writer.Write(vector3.x);
writer.Write(vector3.y);
writer.Write(vector3.z);
writer.WriteArrayEnd();
}
}
// https://github.com/neuecc/MessagePack-CSharp/blob/13c299a5172c60154bae53395612af194c02d286/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Unity/Formatters.cs#L102
public sealed class Vector4Serializer : TypeSerializer
{
public override Type SerializedType { get { return typeof(Vector4); } }
public override object Deserialize(IJsonReader reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (reader.Token == JsonToken.Null)
return null;
var value = new Vector4();
reader.ReadArrayBegin();
int idx = 0;
while (reader.Token != JsonToken.EndOfArray)
value[idx++] = reader.ReadSingle();
reader.ReadArrayEnd(nextToken: false);
return value;
}
public override void Serialize(IJsonWriter writer, object value)
{
if (writer == null) throw new ArgumentNullException("writer");
if (value == null) throw new ArgumentNullException("value");
var vector4 = (Vector4)value;
writer.WriteArrayBegin(4);
writer.Write(vector4.x);
writer.Write(vector4.y);
writer.Write(vector4.z);
writer.Write(vector4.z);
writer.WriteArrayEnd();
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/Encoders/MessagePackProtocol.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1fe4434eade98e547aca1e026a4dbcc3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

178
Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithAuthorizationSample.cs

@ -0,0 +1,178 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using BestHTTP.Examples;
using BestHTTP.Examples.Helpers;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples
{
/// <summary>
/// A sample to demonstrate Bearer token authorization on the server. The client will connect to the /redirect route
/// where it will receive the token and will receive the new url (/HubWithAuthorization) to connect to.
/// HubWithAuthorization without the token would throw an error.
/// </summary>
public sealed class HubWithAuthorizationSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[SerializeField]
private string _path = "/redirect";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
// Instance of the HubConnection
HubConnection hub;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (hub != null)
hub.StartClose();
}
public void OnConnectButton()
{
// Server side of this example can be found here:
// https://github.com/Benedicht/BestHTTP_DemoSite/blob/master/BestHTTP_DemoSite/Hubs/
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(base.sampleSelector.BaseURL + this._path), protocol);
// Subscribe to hub events
hub.OnConnected += Hub_OnConnected;
hub.OnError += Hub_OnError;
hub.OnClosed += Hub_OnClosed;
hub.OnRedirected += Hub_Redirected;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// And finally start to connect to the server
hub.StartConnect();
AddText("StartConnect called");
SetButtons(false, false);
}
public void OnCloseButton()
{
if (hub != null)
{
hub.StartClose();
AddText("StartClose called");
SetButtons(false, false);
}
}
private void Hub_Redirected(HubConnection hub, Uri oldUri, Uri newUri)
{
AddText(string.Format("Hub connection redirected to '<color=green>{0}</color>' with Access Token: '<color=green>{1}</color>'", hub.Uri, hub.NegotiationResult.AccessToken));
}
/// <summary>
/// This callback is called when the plugin is connected to the server successfully. Messages can be sent to the server after this point.
/// </summary>
private void Hub_OnConnected(HubConnection hub)
{
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
SetButtons(false, true);
// Call a parameterless function. We expect a string return value.
hub.Invoke<string>("Echo", "Message from the client")
.OnSuccess(ret => AddText(string.Format("'<color=green>Echo</color>' returned: '<color=yellow>{0}</color>'", ret)).AddLeftPadding(20));
AddText("'<color=green>Message from the client</color>' sent!")
.AddLeftPadding(20);
}
/// <summary>
/// This is called when the hub is closed after a StartClose() call.
/// </summary>
private void Hub_OnClosed(HubConnection hub)
{
AddText("Hub Closed");
SetButtons(true, false);
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
SetButtons(true, false);
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private TextListItem AddText(string text)
{
return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithAuthorizationSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0d6f71c9108b3b419ee412fa4ddd018
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

307
Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithPreAuthorizationSample.cs

@ -0,0 +1,307 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using BestHTTP;
using BestHTTP.Connections;
using BestHTTP.Examples.Helpers;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples
{
public sealed class HubWithPreAuthorizationSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[SerializeField]
private string _hubPath = "/HubWithAuthorization";
[SerializeField]
private string _jwtTokenPath = "/generateJwtToken";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
// Instance of the HubConnection
HubConnection hub;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (hub != null)
hub.StartClose();
}
public void OnConnectButton()
{
// Server side of this example can be found here:
// https://github.com/Benedicht/BestHTTP_DemoSite/blob/master/BestHTTP_DemoSite/Hubs/
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(base.sampleSelector.BaseURL + this._hubPath), protocol);
hub.AuthenticationProvider = new PreAuthAccessTokenAuthenticator(new Uri(base.sampleSelector.BaseURL + this._jwtTokenPath));
hub.AuthenticationProvider.OnAuthenticationSucceded += AuthenticationProvider_OnAuthenticationSucceded;
hub.AuthenticationProvider.OnAuthenticationFailed += AuthenticationProvider_OnAuthenticationFailed;
// Subscribe to hub events
hub.OnConnected += Hub_OnConnected;
hub.OnError += Hub_OnError;
hub.OnClosed += Hub_OnClosed;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// And finally start to connect to the server
hub.StartConnect();
AddText("StartConnect called");
SetButtons(false, false);
}
public void OnCloseButton()
{
if (hub != null)
{
hub.StartClose();
AddText("StartClose called");
SetButtons(false, false);
}
}
private void AuthenticationProvider_OnAuthenticationSucceded(IAuthenticationProvider provider)
{
string str = string.Format("Pre-Authentication Succeded! Token: '<color=green>{0}</color>' ", (hub.AuthenticationProvider as PreAuthAccessTokenAuthenticator).Token);
AddText(str);
}
private void AuthenticationProvider_OnAuthenticationFailed(IAuthenticationProvider provider, string reason)
{
AddText(string.Format("Authentication Failed! Reason: '{0}'", reason));
}
/// <summary>
/// This callback is called when the plugin is connected to the server successfully. Messages can be sent to the server after this point.
/// </summary>
private void Hub_OnConnected(HubConnection hub)
{
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
SetButtons(false, true);
// Call a parameterless function. We expect a string return value.
hub.Invoke<string>("Echo", "Message from the client")
.OnSuccess(ret => AddText(string.Format("'<color=green>Echo</color>' returned: '<color=yellow>{0}</color>'", ret)).AddLeftPadding(20));
AddText("'<color=green>Message from the client</color>' sent!")
.AddLeftPadding(20);
}
/// <summary>
/// This is called when the hub is closed after a StartClose() call.
/// </summary>
private void Hub_OnClosed(HubConnection hub)
{
AddText("Hub Closed");
SetButtons(true, false);
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
SetButtons(true, false);
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private TextListItem AddText(string text)
{
return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
public sealed class PreAuthAccessTokenAuthenticator : IAuthenticationProvider
{
/// <summary>
/// No pre-auth step required for this type of authentication
/// </summary>
public bool IsPreAuthRequired { get { return true; } }
#pragma warning disable 0067
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationFailedDelegate OnAuthenticationFailed;
#pragma warning restore 0067
public string Token { get; private set; }
private Uri authenticationUri;
private HTTPRequest authenticationRequest;
private bool isCancellationRequested;
public PreAuthAccessTokenAuthenticator(Uri authUri)
{
this.authenticationUri = authUri;
}
public void StartAuthentication()
{
this.authenticationRequest = new HTTPRequest(this.authenticationUri, OnAuthenticationRequestFinished);
this.authenticationRequest.Send();
}
private void OnAuthenticationRequestFinished(HTTPRequest req, HTTPResponse resp)
{
switch (req.State)
{
// The request finished without any problem.
case HTTPRequestStates.Finished:
if (resp.IsSuccess)
{
this.authenticationRequest = null;
this.Token = resp.DataAsText;
if (this.OnAuthenticationSucceded != null)
this.OnAuthenticationSucceded(this);
}
else // Internal server error?
AuthenticationFailed(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
resp.StatusCode,
resp.Message,
resp.DataAsText));
break;
// The request finished with an unexpected error. The request's Exception property may contain more info about the error.
case HTTPRequestStates.Error:
AuthenticationFailed("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "" + req.Exception.StackTrace) : "No Exception"));
break;
// The request aborted, initiated by the user.
case HTTPRequestStates.Aborted:
AuthenticationFailed("Request Aborted!");
break;
// Connecting to the server is timed out.
case HTTPRequestStates.ConnectionTimedOut:
AuthenticationFailed("Connection Timed Out!");
break;
// The request didn't finished in the given time.
case HTTPRequestStates.TimedOut:
AuthenticationFailed("Processing the request Timed Out!");
break;
}
}
private void AuthenticationFailed(string reason)
{
this.authenticationRequest = null;
if (this.isCancellationRequested)
return;
if (this.OnAuthenticationFailed != null)
this.OnAuthenticationFailed(this, reason);
}
/// <summary>
/// Prepares the request by adding two headers to it
/// </summary>
public void PrepareRequest(BestHTTP.HTTPRequest request)
{
if (HTTPProtocolFactory.GetProtocolFromUri(request.CurrentUri) == SupportedProtocols.HTTP)
request.Uri = PrepareUri(request.Uri);
}
public Uri PrepareUri(Uri uri)
{
if (!string.IsNullOrEmpty(this.Token))
{
string query = string.IsNullOrEmpty(uri.Query) ? "?" : uri.Query + "&";
UriBuilder uriBuilder = new UriBuilder(uri.Scheme, uri.Host, uri.Port, uri.AbsolutePath, query + "access_token=" + this.Token);
return uriBuilder.Uri;
}
else
return uri;
}
public void Cancel()
{
this.isCancellationRequested = true;
if (this.authenticationRequest != null)
this.authenticationRequest.Abort();
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/HubWithPreAuthorizationSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bfb23ec912f317944b34485c85ab6b31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

34
Assets/Plugins/Best HTTP/Examples/SignalRCore/Person.cs

@ -0,0 +1,34 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using System;
using System.Collections.Generic;
namespace BestHTTP.Examples
{
public enum PersonStates
{
Unknown,
Joined
}
/// <summary>
/// Helper class to demonstrate strongly typed callbacks
/// </summary>
internal sealed class Person
{
public UnityEngine.Vector3[] Positions { get; set; }
public string Name { get; set; }
public long Age { get; set; }
public DateTime Joined { get; set; }
public PersonStates State { get; set; }
public List<Person> Friends { get; set; }
public override string ToString()
{
return string.Format("[Person Name: '{0}', Age: '<color=yellow>{1}</color>', Joined: {2}, State: {3}, Friends: {4}, Position: {5}]",
this.Name, this.Age, this.Joined, this.State, this.Friends != null ? this.Friends.Count : 0, this.Positions != null ? this.Positions.Length : 0);
}
}
}
#endif

13
Assets/Plugins/Best HTTP/Examples/SignalRCore/Person.cs.meta

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 2f03f1530cd505e4d9b16a6b4f2e89c3
timeCreated: 1577715217
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

240
Assets/Plugins/Best HTTP/Examples/SignalRCore/RedirectSample.cs

@ -0,0 +1,240 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using BestHTTP;
using BestHTTP.Connections;
using BestHTTP.Examples.Helpers;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples
{
/// <summary>
/// This sample demonstrates redirection capabilities. The server will redirect a few times the client before
/// routing it to the final endpoint.
/// </summary>
public sealed class RedirectSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[SerializeField]
private string _path = "/redirect_sample";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
// Instance of the HubConnection
public HubConnection hub;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (hub != null)
{
hub.StartClose();
}
}
public void OnConnectButton()
{
// Server side of this example can be found here:
// https://github.com/Benedicht/BestHTTP_DemoSite/blob/master/BestHTTP_DemoSite/Hubs/
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(base.sampleSelector.BaseURL + this._path), protocol);
hub.AuthenticationProvider = new RedirectLoggerAccessTokenAuthenticator(hub);
// Subscribe to hub events
hub.OnConnected += Hub_OnConnected;
hub.OnError += Hub_OnError;
hub.OnClosed += Hub_OnClosed;
hub.OnRedirected += Hub_Redirected;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// And finally start to connect to the server
hub.StartConnect();
AddText("StartConnect called");
SetButtons(false, false);
}
public void OnCloseButton()
{
if (hub != null)
{
AddText("Calling StartClose");
hub.StartClose();
SetButtons(false, false);
}
}
private void Hub_Redirected(HubConnection hub, Uri oldUri, Uri newUri)
{
AddText(string.Format("Hub connection redirected to '<color=green>{0}</color>'!", hub.Uri));
}
/// <summary>
/// This callback is called when the plugin is connected to the server successfully. Messages can be sent to the server after this point.
/// </summary>
private void Hub_OnConnected(HubConnection hub)
{
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
// Call a parameterless function. We expect a string return value.
hub.Invoke<string>("Echo", "Message from the client")
.OnSuccess(ret => AddText(string.Format(" '<color=green>Echo</color>' returned: '<color=yellow>{0}</color>'", ret)));
SetButtons(false, true);
}
/// <summary>
/// This is called when the hub is closed after a StartClose() call.
/// </summary>
private void Hub_OnClosed(HubConnection hub)
{
AddText("Hub Closed");
SetButtons(true, false);
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
SetButtons(true, false);
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private void AddText(string text)
{
GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
public sealed class RedirectLoggerAccessTokenAuthenticator : IAuthenticationProvider
{
/// <summary>
/// No pre-auth step required for this type of authentication
/// </summary>
public bool IsPreAuthRequired { get { return false; } }
#pragma warning disable 0067
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;
/// <summary>
/// Not used event as IsPreAuthRequired is false
/// </summary>
public event OnAuthenticationFailedDelegate OnAuthenticationFailed;
#pragma warning restore 0067
private HubConnection _connection;
public RedirectLoggerAccessTokenAuthenticator(HubConnection connection)
{
this._connection = connection;
}
/// <summary>
/// Not used as IsPreAuthRequired is false
/// </summary>
public void StartAuthentication()
{ }
/// <summary>
/// Prepares the request by adding two headers to it
/// </summary>
public void PrepareRequest(BestHTTP.HTTPRequest request)
{
request.SetHeader("x-redirect-count", _connection.RedirectCount.ToString());
if (HTTPProtocolFactory.GetProtocolFromUri(request.CurrentUri) == SupportedProtocols.HTTP)
request.Uri = PrepareUri(request.Uri);
}
public Uri PrepareUri(Uri uri)
{
if (this._connection.NegotiationResult != null && !string.IsNullOrEmpty(this._connection.NegotiationResult.AccessToken))
{
string query = string.IsNullOrEmpty(uri.Query) ? "?" : uri.Query + "&";
UriBuilder uriBuilder = new UriBuilder(uri.Scheme, uri.Host, uri.Port, uri.AbsolutePath, query + "access_token=" + this._connection.NegotiationResult.AccessToken);
return uriBuilder.Uri;
}
else
return uri;
}
public void Cancel()
{ }
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/RedirectSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: febf35a5598c76843a7573e8f650079e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

242
Assets/Plugins/Best HTTP/Examples/SignalRCore/TestHubSample.cs

@ -0,0 +1,242 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using System;
using UnityEngine;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using UnityEngine.UI;
using BestHTTP.Examples.Helpers;
namespace BestHTTP.Examples
{
public enum MyEnum : int
{
None,
One,
Two
}
public sealed class Metadata
{
public string strData;
public int intData;
public MyEnum myEnum;
}
// Server side of this example can be found here:
// https://github.com/Benedicht/BestHTTP_DemoSite/blob/master/BestHTTP_DemoSite/Hubs/TestHub.cs
public class TestHubSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[SerializeField]
private string _path = "/TestHub";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
// Instance of the HubConnection
HubConnection hub;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (hub != null)
hub.StartClose();
}
/// <summary>
/// GUI button callback
/// </summary>
public void OnConnectButton()
{
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(base.sampleSelector.BaseURL + this._path), protocol);
// Optionally add an authenticator
//hub.AuthenticationProvider = new BestHTTP.SignalRCore.Authentication.HeaderAuthenticator("<generated jwt token goes here>");
// Subscribe to hub events
hub.OnConnected += Hub_OnConnected;
hub.OnError += Hub_OnError;
hub.OnClosed += Hub_OnClosed;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// Set up server callable functions
hub.On("Send", (string arg) => AddText(string.Format("On '<color=green>Send</color>': '<color=yellow>{0}</color>'", arg)).AddLeftPadding(20));
hub.On<Person>("Person", (person) => AddText(string.Format("On '<color=green>Person</color>': '<color=yellow>{0}</color>'", person)).AddLeftPadding(20));
hub.On<Person, Person>("TwoPersons", (person1, person2) => AddText(string.Format("On '<color=green>TwoPersons</color>': '<color=yellow>{0}</color>', '<color=yellow>{1}</color>'", person1, person2)).AddLeftPadding(20));
// And finally start to connect to the server
hub.StartConnect();
AddText("StartConnect called");
SetButtons(false, false);
}
/// <summary>
/// GUI button callback
/// </summary>
public void OnCloseButton()
{
if (this.hub != null)
{
this.hub.StartClose();
AddText("StartClose called");
SetButtons(false, false);
}
}
/// <summary>
/// This callback is called when the plugin is connected to the server successfully. Messages can be sent to the server after this point.
/// </summary>
private void Hub_OnConnected(HubConnection hub)
{
SetButtons(false, true);
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
hub.Send("SendMetadata", new Metadata() { intData = 123, strData = "meta data", myEnum = MyEnum.One });
// Call a server function with a string param. We expect no return value.
hub.Send("Send", "my message");
// Call a parameterless function. We expect a string return value.
hub.Invoke<string>("NoParam")
.OnSuccess(ret => AddText(string.Format("'<color=green>NoParam</color>' returned: '<color=yellow>{0}</color>'", ret)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>NoParam</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// Call a function on the server to add two numbers. OnSuccess will be called with the result and OnError if there's an error.
hub.Invoke<int>("Add", 10, 20)
.OnSuccess(result => AddText(string.Format("'<color=green>Add(10, 20)</color>' returned: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>Add(10, 20)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
hub.Invoke<int?>("NullableTest", 10)
.OnSuccess(result => AddText(string.Format("'<color=green>NullableTest(10)</color>' returned: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>NullableTest(10)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// Call a function that will return a Person object constructed from the function's parameters.
hub.Invoke<Person>("GetPerson", "Mr. Smith", 26)
.OnSuccess(result => AddText(string.Format("'<color=green>GetPerson(\"Mr. Smith\", 26)</color>' returned: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>GetPerson(\"Mr. Smith\", 26)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// To test errors/exceptions this call always throws an exception on the server side resulting in an OnError call.
// OnError expected here!
hub.Invoke<int>("SingleResultFailure", 10, 20)
.OnSuccess(result => AddText(string.Format("'<color=green>SingleResultFailure(10, 20)</color>' returned: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>SingleResultFailure(10, 20)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// This call demonstrates IEnumerable<> functions, result will be the yielded numbers.
hub.Invoke<int[]>("Batched", 10)
.OnSuccess(result => AddText(string.Format("'<color=green>Batched(10)</color>' returned items: '<color=yellow>{0}</color>'", result.Length)).AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>Batched(10)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// OnItem is called for a streaming request for every items returned by the server. OnSuccess will still be called with all the items.
hub.GetDownStreamController<int>("ObservableCounter", 10, 1000)
.OnItem(result => AddText(string.Format("'<color=green>ObservableCounter(10, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>ObservableCounter(10, 1000)</color>' OnSuccess.").AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>ObservableCounter(10, 1000)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// A stream request can be cancelled any time.
var controller = hub.GetDownStreamController<int>("ChannelCounter", 10, 1000);
controller.OnItem(result => AddText(string.Format("'<color=green>ChannelCounter(10, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>ChannelCounter(10, 1000)</color>' OnSuccess.").AddLeftPadding(20))
.OnError(error => AddText(string.Format("'<color=green>ChannelCounter(10, 1000)</color>' error: '<color=red>{0}</color>'", error)).AddLeftPadding(20));
// a stream can be cancelled by calling the controller's Cancel method
controller.Cancel();
// This call will stream strongly typed objects
hub.GetDownStreamController<Person>("GetRandomPersons", 20, 2000)
.OnItem(result => AddText(string.Format("'<color=green>GetRandomPersons(20, 1000)</color>' OnItem: '<color=yellow>{0}</color>'", result)).AddLeftPadding(20))
.OnSuccess(result => AddText("'<color=green>GetRandomPersons(20, 1000)</color>' OnSuccess.").AddLeftPadding(20));
}
/// <summary>
/// This is called when the hub is closed after a StartClose() call.
/// </summary>
private void Hub_OnClosed(HubConnection hub)
{
SetButtons(true, false);
AddText("Hub Closed");
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
SetButtons(true, false);
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private TextListItem AddText(string text)
{
return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
}
#endif

11
Assets/Plugins/Best HTTP/Examples/SignalRCore/TestHubSample.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bd28a72bf1727542937e09ab435abcc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

404
Assets/Plugins/Best HTTP/Examples/SignalRCore/UploadHubSample.cs

@ -0,0 +1,404 @@
#if !BESTHTTP_DISABLE_SIGNALR_CORE
using BestHTTP;
using BestHTTP.Examples.Helpers;
using BestHTTP.SignalRCore;
using BestHTTP.SignalRCore.Encoders;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples
{
/// <summary>
/// This sample demonstrates redirection capabilities. The server will redirect a few times the client before
/// routing it to the final endpoint.
/// </summary>
public sealed class UploadHubSample : BestHTTP.Examples.Helpers.SampleBase
{
#pragma warning disable 0649
[SerializeField]
private string _path = "/uploading";
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
[SerializeField]
private float _yieldWaitTime = 0.1f;
#pragma warning restore
// Instance of the HubConnection
private HubConnection hub;
protected override void Start()
{
base.Start();
SetButtons(true, false);
}
void OnDestroy()
{
if (hub != null)
{
hub.StartClose();
}
}
public void OnConnectButton()
{
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
try
{
MessagePack.Resolvers.StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
MessagePack.Unity.UnityResolver.Instance,
//MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
//MessagePack.Resolvers.StandardResolver.Instance,
MessagePack.Resolvers.ContractlessStandardResolver.Instance
);
var options = MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.StaticCompositeResolver.Instance);
MessagePack.MessagePackSerializer.DefaultOptions = options;
}
catch
{ }
#endif
IProtocol protocol = null;
#if BESTHTTP_SIGNALR_CORE_ENABLE_MESSAGEPACK_CSHARP
protocol = new MessagePackCSharpProtocol();
#elif BESTHTTP_SIGNALR_CORE_ENABLE_GAMEDEVWARE_MESSAGEPACK
protocol = new MessagePackProtocol();
#else
protocol = new JsonProtocol(new LitJsonEncoder());
#endif
// Crete the HubConnection
hub = new HubConnection(new Uri(this.sampleSelector.BaseURL + this._path), protocol);
// Subscribe to hub events
hub.OnConnected += Hub_OnConnected;
hub.OnError += Hub_OnError;
hub.OnClosed += Hub_OnClosed;
hub.OnRedirected += Hub_Redirected;
hub.OnTransportEvent += (hub, transport, ev) => AddText(string.Format("Transport(<color=green>{0}</color>) event: <color=green>{1}</color>", transport.TransportType, ev));
// And finally start to connect to the server
hub.StartConnect();
AddText("StartConnect called");
SetButtons(false, false);
}
public void OnCloseButton()
{
if (this.hub != null)
{
this.hub.StartClose();
AddText("StartClose called");
SetButtons(false, false);
}
}
private void Hub_Redirected(HubConnection hub, Uri oldUri, Uri newUri)
{
AddText(string.Format("Hub connection redirected to '<color=green>{0}</color>'!", hub.Uri));
}
/// <summary>
/// This callback is called when the plugin is connected to the server successfully. Messages can be sent to the server after this point.
/// </summary>
private void Hub_OnConnected(HubConnection hub)
{
AddText(string.Format("Hub Connected with <color=green>{0}</color> transport using the <color=green>{1}</color> encoder.", hub.Transport.TransportType.ToString(), hub.Protocol.Name));
StartCoroutine(UploadWord());
SetButtons(false, true);
}
private IEnumerator UploadWord()
{
AddText("<color=green>UploadWord</color>:");
var controller = hub.GetUpStreamController<string, string>("UploadWord");
controller.OnSuccess(result =>
{
AddText(string.Format("UploadWord completed, result: '<color=yellow>{0}</color>'", result))
.AddLeftPadding(20);
AddText("");
StartCoroutine(ScoreTracker());
});
yield return new WaitForSeconds(_yieldWaitTime);
controller.UploadParam("Hello ");
AddText("'<color=green>Hello </color>' uploaded!")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
controller.UploadParam("World");
AddText("'<color=green>World</color>' uploaded!")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
controller.UploadParam("!!");
AddText("'<color=green>!!</color>' uploaded!")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
controller.Finish();
AddText("Sent upload finished message.")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
}
private IEnumerator ScoreTracker()
{
AddText("<color=green>ScoreTracker</color>:");
var controller = hub.GetUpStreamController<string, int, int>("ScoreTracker");
controller.OnSuccess(result =>
{
AddText(string.Format("ScoreTracker completed, result: '<color=yellow>{0}</color>'", result))
.AddLeftPadding(20);
AddText("");
StartCoroutine(ScoreTrackerWithParameterChannels());
});
const int numScores = 5;
for (int i = 0; i < numScores; i++)
{
yield return new WaitForSeconds(_yieldWaitTime);
int p1 = UnityEngine.Random.Range(0, 10);
int p2 = UnityEngine.Random.Range(0, 10);
controller.UploadParam(p1, p2);
AddText(string.Format("Score({0}/{1}) uploaded! p1's score: <color=green>{2}</color> p2's score: <color=green>{3}</color>", i + 1, numScores, p1, p2))
.AddLeftPadding(20);
}
yield return new WaitForSeconds(_yieldWaitTime);
controller.Finish();
AddText("Sent upload finished message.")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
}
private IEnumerator ScoreTrackerWithParameterChannels()
{
AddText("<color=green>ScoreTracker using upload channels</color>:");
using (var controller = hub.GetUpStreamController<string, int, int>("ScoreTracker"))
{
controller.OnSuccess(result =>
{
AddText(string.Format("ScoreTracker completed, result: '<color=yellow>{0}</color>'", result))
.AddLeftPadding(20);
AddText("");
StartCoroutine(StreamEcho());
});
const int numScores = 5;
// While the server's ScoreTracker has two parameters, we can upload those parameters separately
// So here we
using (var player1param = controller.GetUploadChannel<int>(0))
{
for (int i = 0; i < numScores; i++)
{
yield return new WaitForSeconds(_yieldWaitTime);
int score = UnityEngine.Random.Range(0, 10);
player1param.Upload(score);
AddText(string.Format("Player 1's score({0}/{1}) uploaded! Score: <color=green>{2}</color>", i + 1, numScores, score))
.AddLeftPadding(20);
}
}
AddText("");
using (var player2param = controller.GetUploadChannel<int>(1))
{
for (int i = 0; i < numScores; i++)
{
yield return new WaitForSeconds(_yieldWaitTime);
int score = UnityEngine.Random.Range(0, 10);
player2param.Upload(score);
AddText(string.Format("Player 2's score({0}/{1}) uploaded! Score: <color=green>{2}</color>", i + 1, numScores, score))
.AddLeftPadding(20);
}
}
AddText("All scores uploaded!")
.AddLeftPadding(20);
}
yield return new WaitForSeconds(_yieldWaitTime);
}
private IEnumerator StreamEcho()
{
AddText("<color=green>StreamEcho</color>:");
using (var controller = hub.GetUpAndDownStreamController<string, string>("StreamEcho"))
{
controller.OnSuccess(result =>
{
AddText("StreamEcho completed!")
.AddLeftPadding(20);
AddText("");
StartCoroutine(PersonEcho());
});
controller.OnItem(item =>
{
AddText(string.Format("Received from server: '<color=yellow>{0}</color>'", item))
.AddLeftPadding(20);
});
const int numMessages = 5;
for (int i = 0; i < numMessages; i++)
{
yield return new WaitForSeconds(_yieldWaitTime);
string message = string.Format("Message from client {0}/{1}", i + 1, numMessages);
controller.UploadParam(message);
AddText(string.Format("Sent message to the server: <color=green>{0}</color>", message))
.AddLeftPadding(20);
}
yield return new WaitForSeconds(_yieldWaitTime);
}
AddText("Upload finished!")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
}
/// <summary>
/// This is basically the same as the previous StreamEcho, but it's streaming a complex object (Person
/// </summary>
private IEnumerator PersonEcho()
{
AddText("<color=green>PersonEcho</color>:");
using (var controller = hub.GetUpAndDownStreamController<Person, Person>("PersonEcho"))
{
controller.OnSuccess(result =>
{
AddText("PersonEcho completed!")
.AddLeftPadding(20);
AddText("");
AddText("All Done!");
});
controller.OnItem(item =>
{
AddText(string.Format("Received from server: '<color=yellow>{0}</color>'", item))
.AddLeftPadding(20);
});
const int numMessages = 5;
for (int i = 0; i < numMessages; i++)
{
yield return new WaitForSeconds(_yieldWaitTime);
Person person = new Person()
{
Name = "Mr. Smith",
Age = 20 + i * 2
};
controller.UploadParam(person);
AddText(string.Format("Sent person to the server: <color=green>{0}</color>", person))
.AddLeftPadding(20);
}
yield return new WaitForSeconds(_yieldWaitTime);
}
AddText("Upload finished!")
.AddLeftPadding(20);
yield return new WaitForSeconds(_yieldWaitTime);
}
/// <summary>
/// This is called when the hub is closed after a StartClose() call.
/// </summary>
private void Hub_OnClosed(HubConnection hub)
{
AddText("Hub Closed");
SetButtons(true, false);
}
/// <summary>
/// Called when an unrecoverable error happen. After this event the hub will not send or receive any messages.
/// </summary>
private void Hub_OnError(HubConnection hub, string error)
{
AddText(string.Format("Hub Error: <color=red>{0}</color>", error));
SetButtons(true, false);
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
private TextListItem AddText(string text)
{
return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
}
}
#endif

12
Assets/Plugins/Best HTTP/Examples/SignalRCore/UploadHubSample.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c462c96cbe15002418d1e7a4850a1bb1
timeCreated: 1548919763
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SocketIO.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c66af72c0f511ab44aa91600813e6280
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Plugins/Best HTTP/Examples/SocketIO/SocketIO Json Encoders.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe22d8907a4087949a70b00d13b1b9a7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

27
Assets/Plugins/Best HTTP/Examples/SocketIO/SocketIO Json Encoders/JsonDotNetEncoder.cs

@ -0,0 +1,27 @@
#if !BESTHTTP_DISABLE_SOCKETIO
using System;
using System.Collections.Generic;
namespace BestHTTP.SocketIO.JsonEncoders
{
/*using Newtonsoft.Json;
/// <summary>
/// This class uses Newtonsoft's Json encoder (JSON .NET For Unity - http://u3d.as/5q2).
/// </summary>
public sealed class JsonDotNetEncoder : IJsonEncoder
{
public List<object> Decode(string json)
{
return JsonConvert.DeserializeObject<List<object>>(json);
}
public string Encode(List<object> obj)
{
return JsonConvert.SerializeObject(obj);
}
}*/
}
#endif

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save