├── .github └── FUNDING.yml ├── .gitignore ├── HttpsUtility.sln ├── HttpsUtility ├── Diagnostics │ ├── AssertionException.cs │ ├── Debug.cs │ └── DebugLevel.cs ├── Extensions.cs ├── Https │ ├── HttpsClientPool.cs │ └── HttpsResult.cs ├── HttpsUtility.csproj ├── HttpsUtility.projectinfo ├── Lazy.cs ├── ObjectPool.cs ├── Properties │ └── AssemblyInfo.cs └── Symbols │ ├── SimplHttpsClient.Callbacks.cs │ ├── SimplHttpsClient.Delegates.cs │ └── SimplHttpsClient.cs ├── LICENSE └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: bitm0de 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### VisualStudio template 3 | ## Ignore Visual Studio temporary files, build results, and 4 | ## files generated by popular Visual Studio add-ons. 5 | ## 6 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | bld/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015/2017 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # Visual Studio 2017 auto generated files 35 | Generated\ Files/ 36 | 37 | # MSTest test Results 38 | [Tt]est[Rr]esult*/ 39 | [Bb]uild[Ll]og.* 40 | 41 | # NUNIT 42 | *.VisualState.xml 43 | TestResult.xml 44 | 45 | # Build Results of an ATL Project 46 | [Dd]ebugPS/ 47 | [Rr]eleasePS/ 48 | dlldata.c 49 | 50 | # Benchmark Results 51 | BenchmarkDotNet.Artifacts/ 52 | 53 | # .NET Core 54 | project.lock.json 55 | project.fragment.lock.json 56 | artifacts/ 57 | 58 | # StyleCop 59 | StyleCopReport.xml 60 | 61 | # Files built by Visual Studio 62 | *_i.c 63 | *_p.c 64 | *_i.h 65 | *.ilk 66 | *.meta 67 | *.obj 68 | *.iobj 69 | *.pch 70 | *.pdb 71 | *.ipdb 72 | *.pgc 73 | *.pgd 74 | *.rsp 75 | *.sbr 76 | *.tlb 77 | *.tli 78 | *.tlh 79 | *.tmp 80 | *.tmp_proj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.svclog 87 | *.scc 88 | 89 | # Chutzpah Test files 90 | _Chutzpah* 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opendb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | *.VC.db 101 | *.VC.VC.opendb 102 | 103 | # Visual Studio profiler 104 | *.psess 105 | *.vsp 106 | *.vspx 107 | *.sap 108 | 109 | # Visual Studio Trace Files 110 | *.e2e 111 | 112 | # TFS 2012 Local Workspace 113 | $tf/ 114 | 115 | # Guidance Automation Toolkit 116 | *.gpState 117 | 118 | # ReSharper is a .NET coding add-in 119 | _ReSharper*/ 120 | *.[Rr]e[Ss]harper 121 | *.DotSettings.user 122 | 123 | # JustCode is a .NET coding add-in 124 | .JustCode 125 | 126 | # TeamCity is a build add-in 127 | _TeamCity* 128 | 129 | # DotCover is a Code Coverage Tool 130 | *.dotCover 131 | 132 | # AxoCover is a Code Coverage Tool 133 | .axoCover/* 134 | !.axoCover/settings.json 135 | 136 | # Visual Studio code coverage results 137 | *.coverage 138 | *.coveragexml 139 | 140 | # NCrunch 141 | _NCrunch_* 142 | .*crunch*.local.xml 143 | nCrunchTemp_* 144 | 145 | # MightyMoose 146 | *.mm.* 147 | AutoTest.Net/ 148 | 149 | # Web workbench (sass) 150 | .sass-cache/ 151 | 152 | # Installshield output folder 153 | [Ee]xpress/ 154 | 155 | # DocProject is a documentation generator add-in 156 | DocProject/buildhelp/ 157 | DocProject/Help/*.HxT 158 | DocProject/Help/*.HxC 159 | DocProject/Help/*.hhc 160 | DocProject/Help/*.hhk 161 | DocProject/Help/*.hhp 162 | DocProject/Help/Html2 163 | DocProject/Help/html 164 | 165 | # Click-Once directory 166 | publish/ 167 | 168 | # Publish Web Output 169 | *.[Pp]ublish.xml 170 | *.azurePubxml 171 | # Note: Comment the next line if you want to checkin your web deploy settings, 172 | # but database connection strings (with potential passwords) will be unencrypted 173 | *.pubxml 174 | *.publishproj 175 | 176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 177 | # checkin your Azure Web App publish settings, but sensitive information contained 178 | # in these scripts will be unencrypted 179 | PublishScripts/ 180 | 181 | # NuGet Packages 182 | *.nupkg 183 | # The packages folder can be ignored because of Package Restore 184 | **/[Pp]ackages/* 185 | # except build/, which is used as an MSBuild target. 186 | !**/[Pp]ackages/build/ 187 | # Uncomment if necessary however generally it will be regenerated when needed 188 | #!**/[Pp]ackages/repositories.config 189 | # NuGet v3's project.json files produces more ignorable files 190 | *.nuget.props 191 | *.nuget.targets 192 | 193 | # Microsoft Azure Build Output 194 | csx/ 195 | *.build.csdef 196 | 197 | # Microsoft Azure Emulator 198 | ecf/ 199 | rcf/ 200 | 201 | # Windows Store app package directories and files 202 | AppPackages/ 203 | BundleArtifacts/ 204 | Package.StoreAssociation.xml 205 | _pkginfo.txt 206 | *.appx 207 | 208 | # Visual Studio cache files 209 | # files ending in .cache can be ignored 210 | *.[Cc]ache 211 | # but keep track of directories ending in .cache 212 | !*.[Cc]ache/ 213 | 214 | # Others 215 | ClientBin/ 216 | ~$* 217 | *~ 218 | *.dbmdl 219 | *.dbproj.schemaview 220 | *.jfm 221 | *.pfx 222 | *.publishsettings 223 | orleans.codegen.cs 224 | 225 | # Including strong name files can present a security risk 226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 227 | #*.snk 228 | 229 | # Since there are multiple workflows, uncomment next line to ignore bower_components 230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 231 | #bower_components/ 232 | 233 | # RIA/Silverlight projects 234 | Generated_Code/ 235 | 236 | # Backup & report files from converting an old project file 237 | # to a newer Visual Studio version. Backup files are not needed, 238 | # because we have git ;-) 239 | _UpgradeReport_Files/ 240 | Backup*/ 241 | UpgradeLog*.XML 242 | UpgradeLog*.htm 243 | ServiceFabricBackup/ 244 | *.rptproj.bak 245 | 246 | # SQL Server files 247 | *.mdf 248 | *.ldf 249 | *.ndf 250 | 251 | # Business Intelligence projects 252 | *.rdl.data 253 | *.bim.layout 254 | *.bim_*.settings 255 | *.rptproj.rsuser 256 | 257 | # Microsoft Fakes 258 | FakesAssemblies/ 259 | 260 | # GhostDoc plugin setting file 261 | *.GhostDoc.xml 262 | 263 | # Node.js Tools for Visual Studio 264 | .ntvs_analysis.dat 265 | node_modules/ 266 | 267 | # Visual Studio 6 build log 268 | *.plg 269 | 270 | # Visual Studio 6 workspace options file 271 | *.opt 272 | 273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 274 | *.vbw 275 | 276 | # Visual Studio LightSwitch build output 277 | **/*.HTMLClient/GeneratedArtifacts 278 | **/*.DesktopClient/GeneratedArtifacts 279 | **/*.DesktopClient/ModelManifest.xml 280 | **/*.Server/GeneratedArtifacts 281 | **/*.Server/ModelManifest.xml 282 | _Pvt_Extensions 283 | 284 | # Paket dependency manager 285 | .paket/paket.exe 286 | paket-files/ 287 | 288 | # FAKE - F# Make 289 | .fake/ 290 | 291 | # JetBrains Rider 292 | .idea/ 293 | *.sln.iml 294 | 295 | # CodeRush 296 | .cr/ 297 | 298 | # Python Tools for Visual Studio (PTVS) 299 | __pycache__/ 300 | *.pyc 301 | 302 | # Cake - Uncomment if you are using it 303 | # tools/** 304 | # !tools/packages.config 305 | 306 | # Tabs Studio 307 | *.tss 308 | 309 | # Telerik's JustMock configuration file 310 | *.jmconfig 311 | 312 | # BizTalk build output 313 | *.btp.cs 314 | *.btm.cs 315 | *.odx.cs 316 | *.xsd.cs 317 | 318 | # OpenCover UI analysis results 319 | OpenCover/ 320 | 321 | # Azure Stream Analytics local run output 322 | ASALocalRun/ 323 | 324 | # MSBuild Binary and Structured Log 325 | *.binlog 326 | 327 | # NVidia Nsight GPU debugger configuration file 328 | *.nvuser 329 | 330 | # MFractors (Xamarin productivity tool) working folder 331 | .mfractor/ 332 | 333 | -------------------------------------------------------------------------------- /HttpsUtility.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpsUtility", "HttpsUtility\HttpsUtility.csproj", "{20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /HttpsUtility/Diagnostics/AssertionException.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | 26 | namespace HttpsUtility.Diagnostics 27 | { 28 | /// 29 | /// Exception class for assertion failures. 30 | /// 31 | [Serializable] 32 | internal class AssertionException : Exception 33 | { 34 | public AssertionException() { } 35 | public AssertionException(string message) : base(message) { } 36 | public AssertionException(string message, Exception inner) : base(message, inner) { } 37 | } 38 | } -------------------------------------------------------------------------------- /HttpsUtility/Diagnostics/Debug.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | using System.Text; 26 | using Crestron.SimplSharp; 27 | using Crestron.SimplSharp.CrestronIO; 28 | using Crestron.SimplSharp.Reflection; 29 | 30 | namespace HttpsUtility.Diagnostics 31 | { 32 | public static class Debug 33 | { 34 | private static bool _enable; 35 | private static readonly CTimer _timer = new CTimer(WriteQueueToDisk, null, Timeout.Infinite, Timeout.Infinite); 36 | private static readonly CCriticalSection _writeLock = new CCriticalSection(); 37 | private static readonly CrestronQueue _queue = new CrestronQueue(1024); 38 | 39 | private static readonly AssemblyName _asmName; 40 | 41 | /// Initializes the debug class 42 | static Debug() 43 | { 44 | try 45 | { 46 | _asmName = Assembly.GetExecutingAssembly().GetName(); 47 | } 48 | catch (Exception ex) 49 | { 50 | CrestronConsole.PrintLine(ex.Message); 51 | throw; 52 | } 53 | } 54 | 55 | public static DebugLevel Levels { get; set; } 56 | 57 | /// Flag for enabling debug mode 58 | public static bool Enable 59 | { 60 | get { return _enable; } 61 | set 62 | { 63 | _enable = value; 64 | if (_enable) 65 | _timer.Reset(0, 5000); 66 | else 67 | _timer.Stop(); 68 | } 69 | } 70 | 71 | private static void WriteQueueToDisk(object _) 72 | { 73 | if (Enable) 74 | { 75 | try 76 | { 77 | if (!_writeLock.TryEnter()) 78 | return; 79 | 80 | if (!_queue.IsEmpty) 81 | { 82 | var sb = new StringBuilder(8192); 83 | while (!_queue.IsEmpty) 84 | { 85 | string logItem; 86 | if (_queue.Dequeue(out logItem)) 87 | sb.Append(logItem); 88 | } 89 | 90 | using (var sw = new StreamWriter(string.Format("\\User\\Logs\\{0} {1:yyyy-MM-dd}.log", _asmName.Name, DateTime.Now), true)) 91 | sw.Write(sb.ToString()); 92 | } 93 | } 94 | finally 95 | { 96 | _writeLock.Leave(); 97 | } 98 | } 99 | } 100 | 101 | /// 102 | /// Private helper method to return formatted message string prefixed with the assembly identifier. 103 | /// 104 | /// Message to be written 105 | /// Format arguments for the message 106 | private static string InternalFormat(string message, params object[] args) 107 | { 108 | return string.Format("[{0:yyyy-MM-dd HH:mm:ss}] {1}: App{2:00} - {3}", DateTime.Now, string.Format("{0} {1}", _asmName.Name, _asmName.Version), 109 | InitialParametersClass.ApplicationNumber, string.Format(message, args)); 110 | } 111 | 112 | /// 113 | /// Private helper method to write formatted message to console prefixed with the assembly identifier. 114 | /// 115 | /// Message to be written 116 | /// Format arguments for the message 117 | private static void InternalWrite(string message, params object[] args) 118 | { 119 | if (Enable) 120 | { 121 | try 122 | { 123 | _writeLock.Enter(); 124 | CrestronInvoke.BeginInvoke(_ => _queue.Enqueue(InternalFormat(message, args))); 125 | } 126 | finally 127 | { 128 | _writeLock.Leave(); 129 | } 130 | } 131 | } 132 | 133 | /// 134 | /// Writes a raw debug message without a newline. 135 | /// 136 | /// Format message to output 137 | /// Format message string arguments (if applicable) 138 | public static void Write(string message, params object[] args) 139 | { 140 | InternalWrite(message, args); 141 | } 142 | 143 | public static void Write(object obj) 144 | { 145 | Write("{0}", obj); 146 | } 147 | 148 | /// 149 | /// Writes a raw debug message with a newline. 150 | /// 151 | /// Format message to output 152 | /// Format message string arguments (if applicable) 153 | public static void WriteLine(string message, params object[] args) 154 | { 155 | Write("{0}\n", string.Format(message, args)); 156 | } 157 | 158 | public static void WriteLine(object obj) 159 | { 160 | WriteLine("{0}", obj); 161 | } 162 | 163 | /// 164 | /// Writes an exception debug message with a newline. 165 | /// 166 | /// Format message to output 167 | /// Format message string arguments (if applicable) 168 | public static void WriteException(string message, params object[] args) 169 | { 170 | if (((int)Levels & (int)DebugLevel.Exception) != 0) 171 | WriteLine("NOTICE: [Exception] {0}", string.Format(message, args)); 172 | } 173 | 174 | public static void WriteException(Exception obj) 175 | { 176 | WriteException("{0}", obj); 177 | } 178 | 179 | /// 180 | /// Writes an error debug message with a newline. 181 | /// 182 | /// Format message to output 183 | /// Format message string arguments (if applicable) 184 | public static void WriteError(string message, params object[] args) 185 | { 186 | if (((int)Levels & (int)DebugLevel.Error) != 0) 187 | WriteLine("Error: {0}", string.Format(message, args)); 188 | } 189 | 190 | public static void WriteError(object obj) 191 | { 192 | WriteError("{0}", obj); 193 | } 194 | 195 | /// 196 | /// Writes a warning debug message with a newline. 197 | /// 198 | /// Format message to output 199 | /// Format message string arguments (if applicable) 200 | public static void WriteWarning(string message, params object[] args) 201 | { 202 | if (((int)Levels & (int)DebugLevel.Warning) != 0) 203 | WriteLine("Warning: {0}", string.Format(message, args)); 204 | } 205 | 206 | public static void WriteWarning(object obj) 207 | { 208 | WriteWarning("{0}", obj); 209 | } 210 | 211 | /// 212 | /// Writes an info debug message with a newline. 213 | /// 214 | /// Format message to output 215 | /// Format message string arguments (if applicable) 216 | public static void WriteInfo(string message, params object[] args) 217 | { 218 | if (((int)Levels & (int)DebugLevel.Info) != 0) 219 | WriteLine("Info: {0}", string.Format(message, args)); 220 | } 221 | 222 | public static void WriteInfo(object obj) 223 | { 224 | WriteInfo("{0}", obj); 225 | } 226 | 227 | public static void Assert(Func condition) 228 | { 229 | Assert(condition, null); 230 | } 231 | 232 | public static void Assert(Func condition, string message) 233 | { 234 | if (!condition.Invoke()) 235 | throw message != null ? new AssertionException(message) : new AssertionException(); 236 | } 237 | } 238 | } -------------------------------------------------------------------------------- /HttpsUtility/Diagnostics/DebugLevel.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | 26 | namespace HttpsUtility.Diagnostics 27 | { 28 | /// 29 | /// Flags to set the debug level verbosity. 30 | /// 31 | [Flags] 32 | public enum DebugLevel 33 | { 34 | Notice = 0, 35 | Info = 1, 36 | Warning = 2, 37 | Error = 4, 38 | Exception = 8, 39 | All = 15 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /HttpsUtility/Extensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | 27 | namespace HttpsUtility 28 | { 29 | /// 30 | /// Class for generic extension methods 31 | /// 32 | internal static class Extensions 33 | { 34 | /// 35 | /// Returns a null string if input is an empty string. 36 | /// 37 | /// Input string 38 | /// Null if empty, otherwise the input itself 39 | public static string NullIfEmpty(this string input) 40 | { 41 | return input == string.Empty ? null : input; 42 | } 43 | 44 | /// 45 | /// Returns an empty string if input is a null string. 46 | /// 47 | /// Input string 48 | /// Empty string if null, otherwise the input itself 49 | public static string EmptyIfNull(this string input) 50 | { 51 | return input ?? string.Empty; 52 | } 53 | 54 | /// 55 | /// Split an input string into chunks specified by a max length 56 | /// 57 | /// Input string 58 | /// Maximum size of each chunk 59 | /// of strings split up into chunks. 60 | /// Input string is null. 61 | /// Max length is less than 1. 62 | public static IEnumerable SplitIntoChunks(this string input, int maxLength) 63 | { 64 | if (input == null) 65 | throw new ArgumentNullException("input"); 66 | 67 | if (maxLength <= 0) 68 | throw new ArgumentException("maxSize must be greater than 0."); 69 | 70 | if (input == string.Empty) 71 | return new[] { string.Empty }; 72 | 73 | int n = 0; 74 | List chunks = new List(input.Length / maxLength); 75 | while (n != input.Length) 76 | { 77 | int length = Math.Min(maxLength, input.Length - n); 78 | chunks.Add(input.Substring(n, length)); 79 | n += length; 80 | } 81 | return chunks; 82 | } 83 | 84 | /// 85 | /// Check to see if a flags enumeration has a specific flag set. 86 | /// 87 | /// Flags enumeration to check 88 | /// Flag to check for 89 | /// 90 | public static bool HasFlag(this Enum variable, Enum value) 91 | { 92 | if (variable == null) 93 | return false; 94 | 95 | if (value == null) 96 | throw new ArgumentNullException("value"); 97 | 98 | // Not as good as the .NET 4 version of this function, but should be good enough 99 | if (!Enum.IsDefined(variable.GetType(), value)) 100 | { 101 | throw new ArgumentException(string.Format( 102 | "Enumeration type mismatch. The flag is of type '{0}', was expecting '{1}'.", 103 | value.GetType(), variable.GetType())); 104 | } 105 | 106 | ulong num = Convert.ToUInt64(value); 107 | return (Convert.ToUInt64(variable) & num) == num; 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /HttpsUtility/Https/HttpsClientPool.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Text; 27 | using Crestron.SimplSharp.Net.Https; 28 | using HttpsUtility.Diagnostics; 29 | 30 | using ContentSource = Crestron.SimplSharp.Net.Https.ContentSource; 31 | using RequestType = Crestron.SimplSharp.Net.Https.RequestType; 32 | 33 | namespace HttpsUtility.Https 34 | { 35 | public sealed class HttpsClientPool : IDisposable 36 | { 37 | private const int HttpsClientPoolSize = 10; 38 | 39 | private readonly ObjectPool> _httpsClientPool 40 | = new ObjectPool>(HttpsClientPoolSize, HttpsClientPoolSize, 41 | () => new Lazy(() => new HttpsClient { 42 | PeerVerification = false, HostVerification = false, 43 | TimeoutEnabled = true, Timeout = 5, KeepAlive = false 44 | })) { CleanupPoolOnDispose = true }; 45 | 46 | private HttpsResult SendRequest(string url, RequestType requestType, IEnumerable> additionalHeaders, string content) 47 | { 48 | var obj = _httpsClientPool.GetFromPool(); 49 | var client = obj.Value; 50 | 51 | try 52 | { 53 | Debug.WriteInfo("Making API GET request to endpoint: {0}", url); 54 | 55 | if (client.ProcessBusy) 56 | client.Abort(); 57 | 58 | var httpsRequest = new HttpsClientRequest { 59 | RequestType = requestType, 60 | Encoding = Encoding.UTF8, 61 | KeepAlive = false, 62 | }; 63 | 64 | if (requestType != RequestType.Get) 65 | { 66 | httpsRequest.ContentSource = ContentSource.ContentString; 67 | httpsRequest.ContentString = content ?? string.Empty; 68 | } 69 | 70 | if (additionalHeaders != null) 71 | { 72 | foreach (var item in additionalHeaders) 73 | httpsRequest.Header.AddHeader(new HttpsHeader(item.Key, item.Value)); 74 | } 75 | 76 | httpsRequest.Url.Parse(url); 77 | 78 | HttpsClientResponse httpResponse = client.Dispatch(httpsRequest); 79 | return new HttpsResult(httpResponse.Code, httpResponse.ResponseUrl, httpResponse.ContentString); 80 | } 81 | catch (Exception ex) 82 | { 83 | Debug.WriteException(ex); 84 | } 85 | finally 86 | { 87 | _httpsClientPool.AddToPool(obj); 88 | } 89 | 90 | return null; 91 | } 92 | 93 | public HttpsResult Get(string url) 94 | { 95 | return Get(url, null); 96 | } 97 | 98 | public HttpsResult Get(string url, IEnumerable> additionalHeaders) 99 | { 100 | return SendRequest(url, RequestType.Get, additionalHeaders, null); 101 | } 102 | 103 | public HttpsResult Post(string url, string value) 104 | { 105 | return Post(url, null, value); 106 | } 107 | 108 | public HttpsResult Post(string url, IEnumerable> additionalHeaders, string value) 109 | { 110 | return SendRequest(url, RequestType.Post, additionalHeaders, value); 111 | } 112 | 113 | public HttpsResult Put(string url, string value) 114 | { 115 | return Put(url, null, value); 116 | } 117 | 118 | public HttpsResult Put(string url, IEnumerable> additionalHeaders, string value) 119 | { 120 | return SendRequest(url, RequestType.Put, additionalHeaders, value); 121 | } 122 | 123 | public HttpsResult Delete(string url) 124 | { 125 | return Delete(url, null); 126 | } 127 | 128 | public HttpsResult Delete(string url, string value) 129 | { 130 | return Delete(url, null, value); 131 | } 132 | 133 | public HttpsResult Delete(string url, IEnumerable> additionalHeaders, string value) 134 | { 135 | return SendRequest(url, RequestType.Delete, additionalHeaders, value); 136 | } 137 | 138 | public void Dispose() 139 | { 140 | _httpsClientPool.Dispose(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /HttpsUtility/Https/HttpsResult.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | namespace HttpsUtility.Https 25 | { 26 | public class HttpsResult 27 | { 28 | private readonly int _status; 29 | public int Status { get { return _status; } } 30 | 31 | private readonly string _responseUrl; 32 | public string ResponseUrl { get { return _responseUrl; } } 33 | 34 | private readonly string _content; 35 | public string Content { get { return _content; } } 36 | 37 | public HttpsResult(int status, string responseUrl, string content) 38 | { 39 | _status = status; 40 | _responseUrl = responseUrl; 41 | _content = content; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /HttpsUtility/HttpsUtility.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Release 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {20ABC9C5-BA5D-4C65-94AD-E87EF71FA36A} 9 | Library 10 | Properties 11 | HttpsUtility 12 | HttpsUtility 13 | {0B4745B0-194B-4BB6-8E21-E9057CA92500};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | WindowsCE 15 | E2BECB1F-8C8C-41ba-B736-9BE7D946A398 16 | 5.0 17 | SmartDeviceProject1 18 | v3.5 19 | Windows CE 20 | 21 | 22 | default 23 | 24 | 25 | .allowedReferenceRelatedFileExtensions 26 | true 27 | full 28 | false 29 | bin\Debug\ 30 | DEBUG;TRACE; 31 | prompt 32 | 4 33 | 512 34 | true 35 | true 36 | off 37 | 38 | 39 | .allowedReferenceRelatedFileExtensions 40 | none 41 | true 42 | bin\Release\ 43 | prompt 44 | 4 45 | 512 46 | true 47 | true 48 | off 49 | 50 | 51 | 52 | 53 | False 54 | ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll 55 | 56 | 57 | False 58 | ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll 59 | 60 | 61 | False 62 | ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | rem S# preparation will execute after these operations 86 | 87 | -------------------------------------------------------------------------------- /HttpsUtility/HttpsUtility.projectinfo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitm0de/HttpsUtility/c9c487947d4b33d40bd63ef4e116ccec2413ac48/HttpsUtility/HttpsUtility.projectinfo -------------------------------------------------------------------------------- /HttpsUtility/Lazy.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | using Crestron.SimplSharp; 26 | 27 | namespace HttpsUtility 28 | { 29 | /// 30 | /// Wrapper for lazy initialization support (before .NET 4.0). 31 | /// 32 | /// Object type to be lazy initialized. 33 | public sealed class Lazy 34 | { 35 | private Box _boxValue; 36 | private volatile bool _initialized; 37 | 38 | [NonSerialized] private readonly Func _valueInitFunc; 39 | [NonSerialized] private readonly CCriticalSection _objLock = new CCriticalSection(); 40 | 41 | public bool Initialized 42 | { 43 | get 44 | { 45 | try 46 | { 47 | _objLock.Enter(); 48 | return _initialized; 49 | } 50 | finally 51 | { 52 | _objLock.Leave(); 53 | } 54 | } 55 | } 56 | 57 | public T Value 58 | { 59 | get 60 | { 61 | if (!_initialized) 62 | { 63 | try 64 | { 65 | _objLock.Enter(); 66 | if (!_initialized) 67 | { 68 | _boxValue = new Box(_valueInitFunc()); 69 | _initialized = true; 70 | } 71 | } 72 | finally 73 | { 74 | _objLock.Leave(); 75 | } 76 | } 77 | 78 | return _boxValue.Value; 79 | } 80 | } 81 | 82 | public Lazy() 83 | : this(() => (T)Activator.CreateInstance(typeof(T))) { } 84 | 85 | public Lazy(Func valueInitFunc) 86 | { 87 | if (valueInitFunc == null) 88 | throw new ArgumentNullException("valueInitFunc"); 89 | 90 | _valueInitFunc = valueInitFunc; 91 | } 92 | 93 | public override string ToString() 94 | { 95 | return _initialized ? Value.ToString() : "null"; 96 | } 97 | 98 | [Serializable] 99 | private class Box 100 | { 101 | internal readonly T Value; 102 | 103 | internal Box(T value) 104 | { 105 | Value = value; 106 | } 107 | } 108 | } 109 | 110 | /// 111 | /// Non-generic class helper 112 | /// 113 | public sealed class Lazy 114 | { 115 | /// 116 | /// Creates a default instance of the specified type. 117 | /// 118 | /// Object type 119 | /// Lazy instance of the specified type. 120 | /// The new() type constraint is placed on this little factory method 121 | /// as a way to still allow for types that aren't restricted by this limitation 122 | /// to be used by the class 123 | public static Lazy CreateNew() 124 | where T : new() 125 | { 126 | return new Lazy(Activator.CreateInstance); 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /HttpsUtility/ObjectPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Crestron.SimplSharp; 3 | 4 | namespace HttpsUtility 5 | { 6 | /// 7 | /// An object pool to help with minimizing GC cleanup and re-allocations. 8 | /// 9 | /// Pool object type. 10 | public sealed class ObjectPool : IDisposable 11 | where T : class, new() 12 | { 13 | private readonly CCriticalSection _disposeLock = new CCriticalSection(); 14 | private readonly CrestronQueue _objectPool; 15 | 16 | private readonly CEvent _queueAddEvent = new CEvent(false, true); 17 | private readonly CEvent _queueReturnEvent = new CEvent(false, true); 18 | private int _currentCount; 19 | private bool _disposed; 20 | 21 | /// 22 | /// 23 | /// Initializes a new object pool. 24 | /// 25 | public ObjectPool() 26 | : this(64) { } 27 | 28 | /// 29 | /// 30 | /// Initializes a new object pool with a specified initial capacity. 31 | /// 32 | /// Initial pool capacity. 33 | public ObjectPool(int initialCapacity) 34 | : this(initialCapacity, -1, () => new T()) { } 35 | 36 | /// 37 | /// Initializes a new object pool with a specified initial and max capacity. 38 | /// A max capacity of -1 indicates there is no limit. 39 | /// 40 | /// Initial pool capacity. 41 | /// Max pool capacity. A value of -1 means the pool has no maximum. 42 | /// Initialization function 43 | /// Invalid initial or max capacity. 44 | public ObjectPool(int initialCapacity, int maxCapacity, Func initFunc) 45 | { 46 | if (initialCapacity < 1) 47 | throw new ArgumentException("Initial capacity cannot be less than 1."); 48 | 49 | if (maxCapacity < -1 || maxCapacity == 0) 50 | throw new ArgumentException("Max capacity cannot be less than 1, except -1 which indicates no limit."); 51 | 52 | if (maxCapacity != -1 && initialCapacity > maxCapacity) 53 | throw new ArgumentException("Initial capacity cannot be greater than max capacity."); 54 | 55 | MaxCapacity = maxCapacity; 56 | _objectPool = new CrestronQueue(initialCapacity); 57 | 58 | if (initialCapacity > 0) 59 | AddToPool(initialCapacity, initFunc); 60 | } 61 | 62 | /// 63 | /// Max capacity of the object pool. 64 | /// 65 | /// A max capacity of -1 indicates there is no maximum capacity. 66 | public int MaxCapacity { get; private set; } 67 | 68 | /// 69 | /// Determines whether internal objects in the queue are disposed 70 | /// when this object is disposed if this pool is holding IDisposable objects. 71 | /// 72 | public bool CleanupPoolOnDispose { get; set; } 73 | 74 | public void Dispose() 75 | { 76 | Dispose(true); 77 | } 78 | 79 | /// 80 | /// Adds (or returns) an object to the pool. 81 | /// 82 | /// 83 | /// If is -1, the object is enqueued immediately. 84 | public void AddToPool(T obj) 85 | { 86 | var newCount = Interlocked.Increment(ref _currentCount); 87 | if (MaxCapacity != -1 && newCount > MaxCapacity) 88 | _queueReturnEvent.Wait(); 89 | 90 | if (_disposed) return; 91 | _objectPool.Enqueue(obj); 92 | _queueAddEvent.Set(); 93 | } 94 | 95 | /// 96 | /// Adds a new object to the pool. 97 | /// 98 | /// Initialization function 99 | /// True if object could be added to the pool; otherwise false. 100 | public bool AddToPool(Func initFunc) 101 | { 102 | return AddToPool(1, initFunc); 103 | } 104 | 105 | /// 106 | /// Adds multiple objects to the pool. 107 | /// 108 | /// Number of instantiated objects to add. 109 | /// Initialization function 110 | /// True if objects could be added to the pool; otherwise false. 111 | public bool AddToPool(int count, Func initFunc) 112 | { 113 | for (var i = 0; i < count; i++) 114 | { 115 | if (_disposed || _currentCount == MaxCapacity) 116 | return false; 117 | 118 | Interlocked.Increment(ref _currentCount); 119 | _objectPool.Enqueue(initFunc.Invoke()); 120 | _queueAddEvent.Set(); 121 | } 122 | 123 | return true; 124 | } 125 | 126 | /// 127 | /// Retrieves an object from the pool. 128 | /// 129 | /// Pool object. 130 | public T GetFromPool() 131 | { 132 | if (_currentCount == 0) 133 | _queueAddEvent.Wait(); 134 | 135 | if (_disposed) return null; 136 | Interlocked.Decrement(ref _currentCount); 137 | var obj = _objectPool.Dequeue(); 138 | _queueReturnEvent.Set(); 139 | return obj; 140 | } 141 | 142 | private void Dispose(bool disposing) 143 | { 144 | _disposed = true; 145 | if (disposing) 146 | { 147 | _queueAddEvent.Set(); 148 | _queueReturnEvent.Set(); 149 | 150 | if (CleanupPoolOnDispose && typeof(IDisposable).IsAssignableFrom(typeof(T))) 151 | while (!_objectPool.IsEmpty) 152 | ((IDisposable)_objectPool.Dequeue()).Dispose(); 153 | 154 | _objectPool.Dispose(); 155 | _queueAddEvent.Dispose(); 156 | _queueReturnEvent.Dispose(); 157 | _disposeLock.Dispose(); 158 | } 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /HttpsUtility/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | [assembly: AssemblyTitle("HttpsUtility")] 4 | [assembly: AssemblyCompany("")] 5 | [assembly: AssemblyProduct("HttpsUtility")] 6 | [assembly: AssemblyCopyright("Copyright © Troy Garner 2019")] 7 | [assembly: AssemblyVersion("1.0.1.*")] 8 | 9 | -------------------------------------------------------------------------------- /HttpsUtility/Symbols/SimplHttpsClient.Callbacks.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | // ReSharper disable UnusedMember.Global 25 | 26 | namespace HttpsUtility.Symbols 27 | { 28 | public sealed partial class SimplHttpsClient 29 | { 30 | public SimplHttpsClientResponseDelegate SimplHttpsClientResponse { get; set; } 31 | 32 | private void OnSimplHttpsClientResponse(int status, string responseUrl, string content, int length) 33 | { 34 | var handler = SimplHttpsClientResponse; 35 | if (handler != null) handler.Invoke((ushort)status, responseUrl.EmptyIfNull(), content.EmptyIfNull(), length); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /HttpsUtility/Symbols/SimplHttpsClient.Delegates.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using Crestron.SimplSharp; 25 | 26 | namespace HttpsUtility.Symbols 27 | { 28 | public delegate void SimplHttpsClientResponseDelegate(ushort status, SimplSharpString responseUrl, SimplSharpString content, int contentLength); 29 | } -------------------------------------------------------------------------------- /HttpsUtility/Symbols/SimplHttpsClient.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Troy Garner 2019 - Present 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Linq; 27 | using Crestron.SimplSharp; 28 | using Crestron.SimplSharp.Reflection; 29 | using HttpsUtility.Diagnostics; 30 | using HttpsUtility.Https; 31 | 32 | namespace HttpsUtility.Symbols 33 | { 34 | // ReSharper disable once UnusedType.Global 35 | public sealed partial class SimplHttpsClient 36 | { 37 | private readonly string _moduleIdentifier; 38 | private readonly HttpsClientPool _httpsClientPool = new HttpsClientPool(); 39 | 40 | public SimplHttpsClient() 41 | { 42 | var asm = Assembly.GetExecutingAssembly().GetName(); 43 | _moduleIdentifier = string.Format("{0} {1}", asm.Name, asm.Version.ToString(2)); 44 | } 45 | 46 | private static IEnumerable> ParseHeaders(string input) 47 | { 48 | if (string.IsNullOrEmpty(input)) 49 | return new KeyValuePair[] { }; 50 | 51 | var headerTokens = input.Split('|'); 52 | return (from header in headerTokens 53 | let n = header.IndexOf(':') 54 | where n != -1 55 | select new KeyValuePair( 56 | header.Substring(0, n).Trim(), 57 | header.Substring(n + 1).Trim()) 58 | ).ToList(); 59 | } 60 | 61 | private ushort MakeRequest(Func action) 62 | { 63 | try 64 | { 65 | var response = action.Invoke(); 66 | if (response == null) 67 | { 68 | Debug.WriteError("HTTPS response object was null."); 69 | return 0; 70 | } 71 | 72 | // Some HTTP(S) responses will not have a message body. 73 | if (response.Content == null) 74 | { 75 | OnSimplHttpsClientResponse(response.Status, response.ResponseUrl, string.Empty, 0); 76 | } 77 | else 78 | { 79 | foreach (var contentChunk in response.Content.SplitIntoChunks(255)) 80 | { 81 | OnSimplHttpsClientResponse(response.Status, response.ResponseUrl, contentChunk, response.Content.Length); 82 | CrestronEnvironment.Sleep(10); // allow a little bit for things to process 83 | } 84 | } 85 | 86 | return (ushort)response.Status; 87 | } 88 | catch (Exception ex) 89 | { 90 | Debug.WriteException(ex); 91 | return 0; 92 | } 93 | } 94 | 95 | public ushort SendGet(string url, string headers) 96 | { 97 | return MakeRequest(() => _httpsClientPool.Get(url, ParseHeaders(headers))); 98 | } 99 | 100 | public ushort SendPost(string url, string headers, string content) 101 | { 102 | return MakeRequest(() => _httpsClientPool.Post(url, ParseHeaders(headers), content.NullIfEmpty())); 103 | } 104 | 105 | public ushort SendPut(string url, string headers, string content) 106 | { 107 | return MakeRequest(() => _httpsClientPool.Put(url, ParseHeaders(headers), content.NullIfEmpty())); 108 | } 109 | 110 | public ushort SendDelete(string url, string headers, string content) 111 | { 112 | return MakeRequest(() => _httpsClientPool.Delete(url, ParseHeaders(headers), content.NullIfEmpty())); 113 | } 114 | 115 | public override string ToString() 116 | { 117 | return _moduleIdentifier; 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Troy Garner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HttpsUtility 2 | A basic HTTPS utility S# module for general use where simple secure web requests are necessary, but complex chains of requests involving cookies, and response parsing is not. This module was intended for simple functionality only, where a custom solution is not needed. 3 | 4 | [![modules](https://img.shields.io/badge/S%23-Modules-brightgreen.svg)](https://sharptoothcode.com) [![release](https://img.shields.io/github/release/bitm0de/HttpsUtility.svg?style=flat)](https://github.com/bitm0de/HttpsUtility/releases) [![downloads](https://img.shields.io/github/downloads/bitm0de/HttpsUtility/total.svg?style=flat)](https://github.com/bitm0de/HttpsUtility/releases) [![issues](https://img.shields.io/github/issues/bitm0de/HttpsUtility.svg?style=flat)](https://github.com/bitm0de/HttpsUtility/issues) [![license](https://img.shields.io/github/license/bitm0de/HttpsUtility.svg?style=flat)](https://github.com/bitm0de/HttpsUtility/blob/master/LICENSE) 5 | 6 | ## Compatibility 7 | | Controller | Supported | 8 | | ----------- | ------------------- | 9 | | MC3 | No Longer Supported | 10 | 11 | ## Information 12 | Multiple headers are supported, the formatting for sending multiple headers to the public functions requires each header to be separated by a `|` character. 13 | 14 | Example: 15 | ```Accept: application/json|Content-Type: application/json``` 16 | 17 | ## Generated API (Intended for use by SIMPL+) 18 | ```cs 19 | namespace HttpsUtility.Symbols 20 | { 21 | // note: type can be instantiated from SIMPL+ 22 | class SimplHttpsClient 23 | { 24 | // class properties 25 | // RegisterDelegate(obj, SimplHttpsClientResponse, SimplHttpsClientResponseHandler); 26 | // CALLBACK FUNCTION SimplHttpsClientResponseHandler(INTEGER status, STRING responseUrl, STRING content, INTEGER length); 27 | DelegateProperty SimplHttpsClientResponseDelegate SimplHttpsClientResponse(INTEGER status, STRING responseUrl, STRING content, INTEGER length); 28 | 29 | // class methods 30 | INTEGER_FUNCTION SendGet(STRING url, STRING headers); 31 | INTEGER_FUNCTION SendPost(STRING url, STRING headers, STRING content); 32 | INTEGER_FUNCTION SendPut(STRING url, STRING headers, STRING content); 33 | INTEGER_FUNCTION SendDelete(STRING url, STRING headers, STRING content); 34 | STRING_FUNCTION ToString(); 35 | SIGNED_LONG_INTEGER_FUNCTION GetHashCode(); 36 | } 37 | } 38 | ``` 39 | 40 | ## Downloads 41 | 42 | * Note: I have no direct affiliation with "SharptoothCode" anymore due to employment changes. I do still have full control over maintaining this repository however. (Current releases on Github will contain the relevant SIMPL Windows and SIMPL+ module files.) 43 | 44 | Latest release is available on the releases section: https://github.com/bitm0de/HttpsUtility/releases 45 | --------------------------------------------------------------------------------