JsonRpc.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // SoftEther VPN Server JSON-RPC Stub code for C#
  2. //
  3. // JsonRpc.cs - JSON-RPC Client Utility Functions
  4. //
  5. // Automatically generated at 2023-05-10 14:43:37 by vpnserver-jsonrpc-codegen
  6. //
  7. // Licensed under the Apache License 2.0
  8. // Copyright (c) 2014-2023 SoftEther VPN Project
  9. using System;
  10. using System.IO;
  11. using System.Net.Security;
  12. using System.Net.Http;
  13. using System.Collections.Generic;
  14. using System.Text;
  15. using System.Security.Cryptography.X509Certificates;
  16. using System.Threading.Tasks;
  17. using Newtonsoft.Json;
  18. namespace SoftEther.JsonRpc
  19. {
  20. /// <summary>
  21. /// Internal utility class
  22. /// </summary>
  23. static class ClientUtil
  24. {
  25. public const int DefaultMaxDepth = 8;
  26. public static string NonNull(this string s) { if (s == null) return ""; else return s; }
  27. public static bool IsEmpty(this string str)
  28. {
  29. if (str == null || str.Trim().Length == 0)
  30. return true;
  31. else
  32. return false;
  33. }
  34. public static bool IsFilled(this string str) => !IsEmpty(str);
  35. public static string ObjectToJson(this object obj, bool include_null = false, bool escape_html = false, int? max_depth = ClientUtil.DefaultMaxDepth, bool compact = false, bool reference_handling = false) => ClientUtil.Serialize(obj, include_null, escape_html, max_depth, compact, reference_handling);
  36. public static T JsonToObject<T>(this string str, bool include_null = false, int? max_depth = ClientUtil.DefaultMaxDepth) => ClientUtil.Deserialize<T>(str, include_null, max_depth);
  37. public static object JsonToObject(this string str, Type type, bool include_null = false, int? max_depth = ClientUtil.DefaultMaxDepth) => ClientUtil.Deserialize(str, type, include_null, max_depth);
  38. public static string Serialize(object obj, bool include_null = false, bool escape_html = false, int? max_depth = ClientUtil.DefaultMaxDepth, bool compact = false, bool reference_handling = false)
  39. {
  40. JsonSerializerSettings setting = new JsonSerializerSettings()
  41. {
  42. MaxDepth = max_depth,
  43. NullValueHandling = include_null ? NullValueHandling.Include : NullValueHandling.Ignore,
  44. ReferenceLoopHandling = ReferenceLoopHandling.Error,
  45. PreserveReferencesHandling = reference_handling ? PreserveReferencesHandling.All : PreserveReferencesHandling.None,
  46. StringEscapeHandling = escape_html ? StringEscapeHandling.EscapeHtml : StringEscapeHandling.Default,
  47. };
  48. return JsonConvert.SerializeObject(obj, compact ? Formatting.None : Formatting.Indented, setting);
  49. }
  50. public static T Deserialize<T>(string str, bool include_null = false, int? max_depth = ClientUtil.DefaultMaxDepth)
  51. => (T)Deserialize(str, typeof(T), include_null, max_depth);
  52. public static object Deserialize(string str, Type type, bool include_null = false, int? max_depth = ClientUtil.DefaultMaxDepth)
  53. {
  54. JsonSerializerSettings setting = new JsonSerializerSettings()
  55. {
  56. MaxDepth = max_depth,
  57. NullValueHandling = include_null ? NullValueHandling.Include : NullValueHandling.Ignore,
  58. ObjectCreationHandling = ObjectCreationHandling.Replace,
  59. ReferenceLoopHandling = ReferenceLoopHandling.Error,
  60. };
  61. return JsonConvert.DeserializeObject(str, type, setting);
  62. }
  63. public static void Print(this object o)
  64. {
  65. string str = o.ObjectToJson();
  66. if (o is string) str = (string)o;
  67. Console.WriteLine(str);
  68. }
  69. }
  70. /// <summary>
  71. /// JSON-RPC exception class
  72. /// </summary>
  73. class JsonRpcException : Exception
  74. {
  75. public JsonRpcError RpcError { get; }
  76. public JsonRpcException(JsonRpcError err)
  77. : base($"Code={err.Code}, Message={err.Message.NonNull()}" +
  78. (err == null || err.Data == null ? "" : $", Data={err.Data.ObjectToJson(compact: true)}"))
  79. {
  80. this.RpcError = err;
  81. }
  82. }
  83. /// <summary>
  84. /// JSON-RPC request class. See https://www.jsonrpc.org/specification
  85. /// </summary>
  86. class JsonRpcRequest
  87. {
  88. [JsonProperty("jsonrpc", Order = 1)]
  89. public string Version { get; set; } = "2.0";
  90. [JsonProperty("id", Order = 2)]
  91. public string Id { get; set; } = null;
  92. [JsonProperty("method", Order = 3)]
  93. public string Method { get; set; } = "";
  94. [JsonProperty("params", Order = 4)]
  95. public object Params { get; set; } = null;
  96. public JsonRpcRequest() { }
  97. public JsonRpcRequest(string method, object param, string id)
  98. {
  99. this.Method = method;
  100. this.Params = param;
  101. this.Id = id;
  102. }
  103. }
  104. /// <summary>
  105. /// JSON-RPC response class with generics
  106. /// </summary>
  107. /// <typeparam name="TResult"></typeparam>
  108. class JsonRpcResponse<TResult>
  109. {
  110. [JsonProperty("jsonrpc", Order = 1)]
  111. public virtual string Version { get; set; } = "2.0";
  112. [JsonProperty("id", NullValueHandling = NullValueHandling.Include, Order = 2)]
  113. public virtual string Id { get; set; } = null;
  114. [JsonProperty("result", Order = 3)]
  115. public virtual TResult Result { get; set; } = default(TResult);
  116. [JsonProperty("error", Order = 4)]
  117. public virtual JsonRpcError Error { get; set; } = null;
  118. [JsonIgnore]
  119. public virtual bool IsError => this.Error != null;
  120. [JsonIgnore]
  121. public virtual bool IsOk => !IsError;
  122. public virtual void ThrowIfError()
  123. {
  124. if (this.IsError) throw new JsonRpcException(this.Error);
  125. }
  126. public override string ToString()
  127. {
  128. return this.ObjectToJson(compact: true);
  129. }
  130. }
  131. /// <summary>
  132. /// JSON-RPC error class. See https://www.jsonrpc.org/specification
  133. /// </summary>
  134. class JsonRpcError
  135. {
  136. public JsonRpcError() { }
  137. public JsonRpcError(int code, string message, object data = null)
  138. {
  139. this.Code = code;
  140. this.Message = message.NonNull();
  141. if (this.Message.IsEmpty()) this.Message = $"JSON-RPC Error {code}";
  142. this.Data = data;
  143. }
  144. [JsonProperty("code")]
  145. public int Code { get; set; } = 0;
  146. [JsonProperty("message")]
  147. public string Message { get; set; } = null;
  148. [JsonProperty("data")]
  149. public object Data { get; set; } = null;
  150. }
  151. /// <summary>
  152. /// JSON-RPC client. See https://www.jsonrpc.org/specification
  153. /// </summary>
  154. class JsonRpcClient
  155. {
  156. HttpClientHandler client_handler;
  157. HttpClient client;
  158. public const int DefaultTimeoutMsecs = 60 * 1000;
  159. public int TimeoutMsecs { get => (int)client.Timeout.TotalMilliseconds; set => client.Timeout = new TimeSpan(0, 0, 0, 0, value); }
  160. public Dictionary<string, string> HttpHeaders { get; } = new Dictionary<string, string>();
  161. string base_url;
  162. /// <summary>
  163. /// JSON-RPC client class constructor
  164. /// </summary>
  165. /// <param name="url">The URL</param>
  166. /// <param name="cert_check_proc">The SSL certificate validation callback</param>
  167. public JsonRpcClient(string url, Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool> cert_check_proc = null)
  168. {
  169. if (cert_check_proc == null) cert_check_proc = (message, cert, chain, errors) => true;
  170. client_handler = new HttpClientHandler();
  171. this.client_handler.AllowAutoRedirect = true;
  172. this.client_handler.MaxAutomaticRedirections = 10;
  173. client_handler.ServerCertificateCustomValidationCallback = cert_check_proc;
  174. client = new HttpClient(client_handler, true);
  175. //Console.WriteLine("new HttpClient(client_handler, true);");
  176. this.base_url = url;
  177. this.TimeoutMsecs = DefaultTimeoutMsecs;
  178. }
  179. /// <summary>
  180. /// Call a single RPC call (without error check). You can wait for the response with Task<string> or await statement.
  181. /// </summary>
  182. /// <param name="method_name">The name of RPC method</param>
  183. /// <param name="param">The parameters</param>
  184. public async Task<string> CallInternalAsync(string method_name, object param)
  185. {
  186. string id = DateTime.Now.Ticks.ToString();
  187. JsonRpcRequest req = new JsonRpcRequest(method_name, param, id);
  188. string req_string = req.ObjectToJson();
  189. //Console.WriteLine($"req: {req_string}");
  190. HttpContent content = new StringContent(req_string, Encoding.UTF8, "application/json");
  191. foreach (string key in this.HttpHeaders.Keys)
  192. {
  193. string value = this.HttpHeaders[key];
  194. content.Headers.Add(key, value);
  195. }
  196. HttpResponseMessage response = await this.client.PostAsync(base_url, content);
  197. Stream responseStream = await response.Content.ReadAsStreamAsync();
  198. if (!response.IsSuccessStatusCode)
  199. {
  200. using (StreamReader streamReader = new StreamReader(responseStream))
  201. {
  202. throw new Exception($"Error: {response.StatusCode}: {await streamReader.ReadToEndAsync()}");
  203. }
  204. }
  205. string ret_string;
  206. using (StreamReader streamReader = new StreamReader(responseStream))
  207. {
  208. ret_string = await streamReader.ReadToEndAsync();
  209. }
  210. //Console.WriteLine($"ret: {ret_string}");
  211. return ret_string;
  212. }
  213. /// <summary>
  214. /// Call a single RPC call (with error check). You can wait for the response with Promise<TResult> or await statement. In the case of error, it will be thrown.
  215. /// </summary>
  216. /// <param name="method_name">The name of RPC method</param>
  217. /// <param name="param">The parameters</param>
  218. public async Task<TResult> CallAsync<TResult>(string method_name, object param)
  219. {
  220. string ret_string = await CallInternalAsync(method_name, param);
  221. JsonRpcResponse <TResult> ret = ret_string.JsonToObject<JsonRpcResponse<TResult>>();
  222. ret.ThrowIfError();
  223. return ret.Result;
  224. }
  225. }
  226. }