private IObservable <PooledArraySegment <byte>[]> ZmqSubscribeEndpoint(DaemonEndpointConfig endPoint, string url, string topic, int numMsgSegments = 2) { return(Observable.Defer(() => Observable.Create <PooledArraySegment <byte>[]>(obs => { var tcs = new CancellationTokenSource(); Task.Factory.StartNew(() => { using (tcs) { while (!tcs.IsCancellationRequested) { try { using (var subSocket = new SubscriberSocket()) { //subSocket.Options.ReceiveHighWatermark = 1000; subSocket.Connect(url); subSocket.Subscribe(topic); logger.Debug($"Subscribed to {url}/{BitcoinConstants.ZmqPublisherTopicBlockHash}"); while (!tcs.IsCancellationRequested) { var msg = subSocket.ReceiveMultipartMessage(numMsgSegments); // Export all frame data as array of PooledArraySegments var result = msg.Select(x => { var buf = ArrayPool <byte> .Shared.Rent(x.BufferSize); Array.Copy(x.ToByteArray(), buf, x.BufferSize); return new PooledArraySegment <byte>(buf, 0, x.BufferSize); }).ToArray(); obs.OnNext(result); } } } catch (Exception ex) { logger.Error(ex); } // do not consume all CPU cycles in case of a long lasting error condition Thread.Sleep(1000); } } }, tcs.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); return Disposable.Create(() => { tcs.Cancel(); }); }))); }
private async Task <JsonRpcResponse <JToken>[]> BuildBatchRequestTask(DaemonEndpointConfig endPoint, DaemonCmd[] batch) { // build rpc request var rpcRequests = batch.Select(x => new JsonRpcRequest <object>(x.Method, x.Payload, GetRequestId())); // build request url var requestUrl = $"http://{endPoint.Host}:{endPoint.Port}"; if (!string.IsNullOrEmpty(rpcLocation)) { requestUrl += $"/{rpcLocation}"; } // build http request using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl)) { var json = JsonConvert.SerializeObject(rpcRequests, serializerSettings); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); // build auth header if (!string.IsNullOrEmpty(endPoint.User)) { var auth = $"{endPoint.User}:{endPoint.Password}"; var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(auth)); request.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64); } // send request var httpClient = httpClients[endPoint]; using (var response = await httpClient.SendAsync(request)) { // check success if (!response.IsSuccessStatusCode) { throw new DaemonClientException(response.StatusCode, response.ReasonPhrase); } // deserialize response using (var stream = await response.Content.ReadAsStreamAsync()) { using (var reader = new StreamReader(stream, Encoding.UTF8)) { using (var jreader = new JsonTextReader(reader)) { var result = serializer.Deserialize <JsonRpcResponse <JToken>[]>(jreader); return(result); } } } } } }
private async Task <JsonRpcResponse> BuildRequestTask(DaemonEndpointConfig endPoint, string method, object payload, JsonSerializerSettings payloadJsonSerializerSettings = null) { var rpcRequestId = GetRequestId(); // build rpc request var rpcRequest = new JsonRpcRequest <object>(method, payload, rpcRequestId); // build request url var requestUrl = $"http://{endPoint.Host}:{endPoint.Port}"; if (!string.IsNullOrEmpty(rpcLocation)) { requestUrl += $"/{rpcLocation}"; } // build http request var request = new HttpRequestMessage(HttpMethod.Post, requestUrl); var json = JsonConvert.SerializeObject(rpcRequest, payloadJsonSerializerSettings ?? serializerSettings); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); // build auth header if (!string.IsNullOrEmpty(endPoint.User)) { var auth = $"{endPoint.User}:{endPoint.Password}"; var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(auth)); request.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64); } // send request var httpClient = httpClients[endPoint]; using (var response = await httpClient.SendAsync(request)) { // deserialize response using (var stream = await response.Content.ReadAsStreamAsync()) { using (var reader = new StreamReader(stream, Encoding.UTF8)) { using (var jreader = new JsonTextReader(reader)) { var result = serializer.Deserialize <JsonRpcResponse>(jreader); return(result); } } } } }
public RpcClient(DaemonEndpointConfig endPoint, JsonSerializerSettings serializerSettings, IMessageBus messageBus, string poolId) { Contract.RequiresNonNull(serializerSettings, nameof(serializerSettings)); Contract.RequiresNonNull(messageBus, nameof(messageBus)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(poolId), $"{nameof(poolId)} must not be empty"); config = endPoint; this.serializerSettings = serializerSettings; this.messageBus = messageBus; this.poolId = poolId; serializer = new JsonSerializer { ContractResolver = serializerSettings.ContractResolver ! }; }
private IObservable <PooledArraySegment <byte> > WebsocketSubscribeEndpoint(DaemonEndpointConfig endPoint, int port, string method, object payload = null, JsonSerializerSettings payloadJsonSerializerSettings = null) { return(Observable.Defer(() => Observable.Create <PooledArraySegment <byte> >(obs => { var cts = new CancellationTokenSource(); var thread = new Thread(async(_) => { using (cts) { while (!cts.IsCancellationRequested) { try { using (var plb = new PooledLineBuffer(logger)) { using (var client = new ClientWebSocket()) { // connect var uri = new Uri($"ws://{endPoint.Host}:{port}"); logger.Debug(() => $"Establishing WebSocket connection to {uri}"); await client.ConnectAsync(uri, cts.Token); // subscribe var buf = ArrayPool <byte> .Shared.Rent(0x10000); try { var request = new JsonRpcRequest(method, payload, GetRequestId()); var json = JsonConvert.SerializeObject(request, payloadJsonSerializerSettings).ToCharArray(); var byteLength = Encoding.UTF8.GetBytes(json, 0, json.Length, buf, 0); var segment = new ArraySegment <byte>(buf, 0, byteLength); logger.Debug(() => $"Sending WebSocket subscription request to {uri}"); await client.SendAsync(segment, WebSocketMessageType.Text, true, cts.Token); // stream response segment = new ArraySegment <byte>(buf); while (!cts.IsCancellationRequested && client.State == WebSocketState.Open) { var response = await client.ReceiveAsync(buf, cts.Token); if (response.MessageType == WebSocketMessageType.Binary) { throw new InvalidDataException("expected text, received binary data"); } plb.Receive(segment, response.Count, (src, dst, count) => Array.Copy(src.Array, src.Offset, dst, 0, count), obs.OnNext, (ex) => { }, response.EndOfMessage); } } finally { ArrayPool <byte> .Shared.Return(buf); } } } } catch (Exception ex) { logger.Error(() => $"{ex.GetType().Name} '{ex.Message}' while streaming websocket responses. Reconnecting in 5s"); } await Task.Delay(TimeSpan.FromSeconds(5), cts.Token); } } }); thread.Start(); return Disposable.Create(() => { cts.Cancel(); }); }))); }