public async Task <WebSocketResponse> SendWebSocketRequestAsync(WebSocketRequest request, bool subscribeAdventure = false) { using var tokenSource = new CancellationTokenSource(); var webSocketRequest = SendWebSocketRequestInternalAsync(request, subscribeAdventure); var completedTask = await Task.WhenAny(webSocketRequest, Task.Delay(30000, tokenSource.Token)); if (completedTask != webSocketRequest) { throw new TimeoutException("Timeout"); } tokenSource.Cancel(); return(await webSocketRequest); }
private async Task <WebSocketResponse> SendWebSocketRequestInternalAsync(WebSocketRequest request, bool subscribeAdventure) { if (string.IsNullOrEmpty(_token)) { throw new InvalidOperationException("Token can't be empty."); } ClientWebSocket webSocket = new ClientWebSocket(); webSocket.Options.AddSubProtocol("graphql-ws"); await webSocket.ConnectAsync(new Uri(WebSocketEndpoint), CancellationToken.None); string initData = "{\"type\":\"connection_init\",\"payload\":{\"token\":\"" + _token + "\"}}"; Debug.WriteLine("sending connection_init"); await webSocket.SendAsync(GetArraySegment(initData), WebSocketMessageType.Text, true, CancellationToken.None); string requestId = "2"; if (subscribeAdventure) { string subscription = "{\"id\":\"1\",\"type\":\"start\",\"payload\":{\"variables\":{\"publicId\":\"" + request.Payload.Variables.Input.PublicId + "\"},\"extensions\":{},\"operationName\":null,\"query\":\"subscription ($publicId: String) {\n subscribeAdventure(publicId: $publicId) {\n id\n ...AdventureControllerFragment\n ...AudioPlayerFragment\n ...PromptReviewFragment\n __typename\n }\n}\n\nfragment AdventureControllerFragment on Adventure {\n id\n actionLoading\n error\n gameState\n thirdPerson\n userId\n characters {\n id\n userId\n name\n __typename\n }\n ...ActionControllerFragment\n ...AlterControllerFragment\n ...QuestControllerFragment\n ...RememberControllerFragment\n ...SafetyControllerFragment\n ...ShareControllerFragment\n __typename\n}\n\nfragment ActionControllerFragment on Adventure {\n id\n publicId\n actionCount\n choices\n error\n mode\n thirdPerson\n userId\n characters {\n id\n userId\n name\n __typename\n }\n ...DeathControllerFragment\n __typename\n}\n\nfragment DeathControllerFragment on Adventure {\n id\n publicId\n mode\n died\n __typename\n}\n\nfragment AlterControllerFragment on Adventure {\n id\n publicId\n mode\n actions {\n id\n text\n __typename\n }\n __typename\n}\n\nfragment QuestControllerFragment on Adventure {\n id\n actions {\n id\n text\n __typename\n }\n quests {\n id\n text\n completed\n active\n actionGainedId\n actionCompletedId\n __typename\n }\n __typename\n}\n\nfragment RememberControllerFragment on Adventure {\n id\n memory\n __typename\n}\n\nfragment SafetyControllerFragment on Adventure {\n id\n hasBannedWord\n hasUserBannedWord\n __typename\n}\n\nfragment ShareControllerFragment on Adventure {\n id\n userId\n thirdPerson\n playPublicId\n characters {\n id\n userId\n name\n __typename\n }\n __typename\n}\n\nfragment AudioPlayerFragment on Adventure {\n id\n music\n actions {\n id\n text\n __typename\n }\n __typename\n}\n\nfragment PromptReviewFragment on Adventure {\n id\n actionCount\n __typename\n}\n\",\"auth\":{\"token\":\"hello\"}}}"; Debug.WriteLine("subscribing to adventure..."); Debug.WriteLine($"send: {subscription}"); await webSocket.SendAsync(GetArraySegment(subscription), WebSocketMessageType.Text, true, CancellationToken.None); } else { requestId = "1"; request.Id = requestId; } string payload = JsonConvert.SerializeObject(request); Debug.WriteLine($"send: {payload}"); await webSocket.SendAsync(GetArraySegment(payload), WebSocketMessageType.Text, true, CancellationToken.None); while (true) { string response; await using (var ms = new MemoryStream()) { var buffer = new ArraySegment <byte>(new byte[8192]); WebSocketReceiveResult result; do { result = await webSocket.ReceiveAsync(buffer, CancellationToken.None); ms.Write(buffer.Array, buffer.Offset, result.Count); }while (!result.EndOfMessage); if (result.MessageType != WebSocketMessageType.Text) { continue; } ms.Seek(0, SeekOrigin.Begin); response = Encoding.UTF8.GetString(ms.ToArray()); } Debug.WriteLine($"receive: {response}"); if (!response.StartsWith("{\"type\":\"data\",", StringComparison.OrdinalIgnoreCase)) { continue; } await Task.Delay(2000); string stop = "{\"id\":\"" + requestId + "\",\"type\":\"stop\"}"; Debug.WriteLine($"send: {stop}"); await webSocket.SendAsync(GetArraySegment(stop), WebSocketMessageType.Text, true, CancellationToken.None); await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); webSocket.Dispose(); return(JsonConvert.DeserializeObject <WebSocketResponse>(response)); } }