private uint CreateContext() { Logger.Debug("Init context"); uint context = 0; using (var configStr = new TonString(_serializer.Serialize(Config))) { var result = Interop.tc_create_context(configStr.ToStruct()); if (result == IntPtr.Zero) { Logger.Error("Init context returned null"); throw new TonClientException($"{nameof(Interop.tc_create_context)} returned null"); } var json = Interop.tc_read_string(result).ToString(); Logger.Debug($"Init context returned JSON: {json}"); Interop.tc_destroy_string(result); var token = JObject.Parse(json); if (token.TryGetValue("result", out var contextToken)) { Logger.Debug($"Init context succeeded: {contextToken}"); context = contextToken.Value <uint>(); } else { if (token.TryGetValue("error", out var errorToken)) { Logger.Debug($"throwing exception with error {errorToken}"); throw TonClientException.FromJson(errorToken.Value <JToken>()); } else { Logger.Debug($"throwing exception with the returned JSON: {json}"); throw TonClientException.FromJson(json); } } } return(context); }
private async Task <string> GetJsonResponse <TC>(string functionName, object @params, Func <TC, int, Task> callback = null) { var functionParamsJson = @params != null ? _serializer.Serialize(@params) : ""; Logger.Debug($"Calling function {functionName} with parameters {functionParamsJson}"); // GCHandle to store reference to the native callback handler. // This is to avoid native handler being garbage collected while waiting // for result from the native lib. var callbackHandle = default(GCHandle); var tcs = new TaskCompletionSource <string>(); var handler = new Interop.tc_response_handler_t((requestId, json_str, type, finished) => { try { var json = json_str.ToString(); Logger.Debug($"{functionName} status update: {type} ({json})"); if (type == (int)Interop.tc_response_types_t.tc_response_success) { tcs.SetResult(json); } else if (type == (int)Interop.tc_response_types_t.tc_response_error) { tcs.SetException(TonClientException.FromJson(json)); } else if (type == (int)Interop.tc_response_types_t.tc_response_nop) { // TODO: ??? } else { if (callback != null) { var value = _serializer.Deserialize <TC>(json); callback.Invoke(value, (int)type); // TODO: call Wait here? } } } finally { if (finished && callbackHandle.IsAllocated) { callbackHandle.Free(); } } }); callbackHandle = GCHandle.Alloc(handler); using (var fNameStr = new TonString(functionName)) { using (var fParamsStr = new TonString(functionParamsJson)) { Interop.tc_request(_context, fNameStr.ToStruct(), fParamsStr.ToStruct(), 1, handler); } } return(await tcs.Task); }