Ejemplo n.º 1
0
        private async Task <BlittableJsonReaderObject> Receive(RavenClientWebSocket webSocket,
                                                               JsonOperationContext context)
        {
            BlittableJsonDocumentBuilder builder = null;

            try
            {
                if (webSocket.State != WebSocketState.Open)
                {
                    throw new InvalidOperationException(
                              $"Trying to 'ReceiveAsync' WebSocket while not in Open state. State is {webSocket.State}");
                }

                var state = new JsonParserState();
                JsonOperationContext.ManagedPinnedBuffer buffer;
                using (context.GetManagedBuffer(out buffer))
                    using (var parser = new UnmanagedJsonParser(context, state, "")) //TODO: FIXME
                    {
                        builder = new BlittableJsonDocumentBuilder(context, BlittableJsonDocumentBuilder.UsageMode.None,
                                                                   nameof(TrafficRec) + "." + nameof(Receive), parser, state);
                        builder.ReadObjectDocument();
                        while (builder.Read() == false)
                        {
                            var result = await webSocket.ReceiveAsync(buffer.Buffer, CancellationToken.None);

                            if (result.MessageType == WebSocketMessageType.Close)
                            {
                                if (Logger.IsInfoEnabled)
                                {
                                    Logger.Info("Client got close message from server and is closing connection");
                                }

                                builder.Dispose();
                                // actual socket close from dispose
                                return(null);
                            }

                            if (result.EndOfMessage == false)
                            {
                                throw new EndOfStreamException("Stream ended without reaching end of json content.");
                            }

                            parser.SetBuffer(buffer, result.Count);
                        }
                        builder.FinalizeDocument();

                        return(builder.CreateReader());
                    }
            }
            catch (WebSocketException ex)
            {
                builder?.Dispose();
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Failed to receive a message, client was probably disconnected", ex);
                }
                throw;
            }
        }
Ejemplo n.º 2
0
        private async Task <RavenJObject> Recieve(RavenClientWebSocket webSocket)
        {
            try
            {
                if (webSocket.State != WebSocketState.Open)
                {
                    throw new InvalidOperationException(
                              $"Trying to 'ReceiveAsync' WebSocket while not in Open state. State is {webSocket.State}");
                }

                using (var ms = new MemoryStream())
                {
                    ArraySegment <byte> bytes;
                    ms.SetLength(MaxWebSocketRecvSize);
                    ms.TryGetBuffer(out bytes);
                    var arraySegment = new ArraySegment <byte>(bytes.Array, 0, MaxWebSocketRecvSize);
                    var result       = await webSocket.ReceiveAsync(arraySegment, disposedToken.Token);

                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        if (Logger.IsDebugEnabled)
                        {
                            Logger.Debug("Client got close message from server and is closing connection");
                        }

                        // actual socket close from dispose
                        return(null);
                    }

                    if (result.EndOfMessage == false)
                    {
                        var err = $"In Recieve got response longer then {MaxWebSocketRecvSize}";
                        var ex  = new InvalidOperationException(err);
                        Logger.DebugException(err, ex);
                        throw ex;
                    }

                    using (var reader = new StreamReader(ms, Encoding.UTF8, true, MaxWebSocketRecvSize, true))
                        using (var jsonReader = new RavenJsonTextReader(reader)
                        {
                            SupportMultipleContent = true
                        })
                        {
                            if (jsonReader.Read() == false)
                            {
                                throw new InvalidDataException("Couldn't read recieved websocket json message");
                            }
                            return(RavenJObject.Load(jsonReader));
                        }
                }
            }
            catch (WebSocketException ex)
            {
                Logger.DebugException("Failed to receive a message, client was probably disconnected", ex);
                throw;
            }
        }
Ejemplo n.º 3
0
        private async Task Send(RavenClientWebSocket webSocket, string command, string commandParameter)
        {
            Logger.Info($"Sending WebSocket Authentication Command {command} - {commandParameter} to {uri}");

            var ravenJObject = new RavenJObject
            {
                [command] = commandParameter,
            };

            var stream = new MemoryStream();

            ravenJObject.WriteTo(stream);
            ArraySegment <byte> bytes;

            stream.TryGetBuffer(out bytes);
            await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false);
        }
Ejemplo n.º 4
0
        private async Task Send(RavenClientWebSocket webSocket, string command, string commandParameter)
        {
            throw new NotImplementedException();

            /*Logger.Info($"Sending WebSocket Authentication Command {command} - {commandParameter} to {uri}");
             *
             * var ravenJObject = new RavenJObject
             * {
             *  [command] = commandParameter,
             * };
             *
             * var stream = new MemoryStream();
             * ravenJObject.WriteTo(stream);
             * ArraySegment<byte> bytes;
             * stream.TryGetBuffer(out bytes);
             * await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false);*/
        }
Ejemplo n.º 5
0
        public async Task <Action <HttpClient> > DoOAuthRequestAsync(string url, string apiKey)
        {
            ThrowIfBadUrlOrApiKey(url, apiKey);
            uri = new Uri(url.ToWebSocketPath());

            using (var webSocket = new RavenClientWebSocket())
            {
                try
                {
                    Logger.Info("Trying to connect using WebSocket to {0} for authentication", uri);
                    try
                    {
                        await webSocket.ConnectAsync(uri, CancellationToken.None);
                    }
                    catch (WebSocketException webSocketException)
                    {
                        throw new InvalidOperationException($"Cannot connect using WebSocket to {uri} for authentication", webSocketException);
                    }
                    var recvRavenJObject = await Recieve(webSocket);

                    var challenge = ComputeChallenge(recvRavenJObject, apiKey);
                    await Send(webSocket, "ChallengeResponse", challenge);

                    recvRavenJObject = await Recieve(webSocket);

                    try
                    {
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close from client", disposedToken.Token);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    SetCurrentTokenFromReply(recvRavenJObject);
                    return(SetAuthorization);
                }
                catch (Exception ex)
                {
                    Logger.DebugException($"Failed to DoOAuthRequest to {url} with {apiKey}", ex);
                    throw;
                }
            }
        }
Ejemplo n.º 6
0
        private async Task Send(RavenClientWebSocket webSocket, JsonOperationContext context, string command, string commandParameter)
        {
            if (Logger.IsInfoEnabled)
            {
                Logger.Info($"Sending WebSocket Authentication Command {command} - {commandParameter}");
            }

            var json = new DynamicJsonValue
            {
                [command] = commandParameter
            };

            using (var stream = new MemoryStream())
                using (var writer = new BlittableJsonTextWriter(context, stream))
                {
                    context.Write(writer, json);
                    writer.Flush();

                    ArraySegment <byte> bytes;
                    stream.TryGetBuffer(out bytes);
                    await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false);
                }
        }
Ejemplo n.º 7
0
        public async Task <BlittableJsonReaderObject> TryReadFromWebSocket(
            JsonOperationContext context,
            RavenClientWebSocket webSocket,
            string debugTag,
            CancellationToken cancellationToken)
        {
            var jsonParserState = new JsonParserState();

            JsonOperationContext.ManagedPinnedBuffer bytes;
            using (context.GetManagedBuffer(out bytes))
                using (var parser = new UnmanagedJsonParser(context, jsonParserState, debugTag))
                {
                    var writer = new BlittableJsonDocumentBuilder(context,
                                                                  BlittableJsonDocumentBuilder.UsageMode.None, debugTag, parser, jsonParserState);

                    writer.ReadObjectDocument();

                    var result = await webSocket.ReceiveAsync(bytes.Buffer, cancellationToken).ConfigureAwait(false);

                    parser.SetBuffer(bytes, result.Count);
                    while (writer.Read() == false)
                    {
                        // we got incomplete json response.
                        // This might happen if we close the connection but still server sends something
                        if (result.CloseStatus != null)
                        {
                            return(null);
                        }

                        result = await webSocket.ReceiveAsync(bytes.Buffer, cancellationToken).ConfigureAwait(false);

                        parser.SetBuffer(bytes, result.Count);
                    }
                    writer.FinalizeDocument();
                    return(writer.CreateReader());
                }
        }
Ejemplo n.º 8
0
        protected RemoteChangesClientBase(
            string url,
            string apiKey,
            ICredentials credentials,
            TConventions conventions,
            Action onDispose)
        {
            // Precondition
            var api = this as TChangesApi;

            if (api == null)
            {
                throw new InvalidCastException(string.Format("The derived class does not implements {0}. Make sure the {0} interface is implemented by this class.", typeof(TChangesApi).Name));
            }

            ConnectionStatusChanged = LogOnConnectionStatusChanged;

            id = Interlocked.Increment(ref connectionCounter) + "/" + Base62Util.Base62Random();

            this.url         = url;
            this.credentials = new OperationCredentials(apiKey, credentials);
            this.onDispose   = onDispose;
            Conventions      = conventions;
            webSocket        = new RavenClientWebSocket();

            ConnectionTask = EstablishConnection()
                             .ObserveException()
                             .ContinueWith(task =>
            {
                task.AssertNotFailed();

                Task.Run(Receive);

                return(this as TChangesApi);
            });
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Connects to raven traffic event source and registers all the requests to the file defined in the config
        /// </summary>
        /// <param name="config">configuration conatining the connection, the file to write to, etc.</param>
        /// <param name="store">the store to work with</param>
        private async Task RecordRequests(TrafficToolConfiguration config, IDocumentStore store)
        {
            var id = Guid.NewGuid().ToString();

            using (var client = new RavenClientWebSocket())
            {
                var url = store.Url + "/traffic-watch/websockets";
                var uri = new Uri(url.ToWebSocketPath());

                await client.ConnectAsync(uri, CancellationToken.None)
                .ConfigureAwait(false);


                // record traffic no more then 7 days
                var day     = 24 * 60 * 60;
                var timeout = (int)config.Timeout.TotalMilliseconds / 1000;
                timeout = Math.Min(timeout, 7 * day);
                if (timeout <= 0)
                {
                    timeout = 7 * day;
                }

                try
                {
                    string resourceName   = config.ResourceName ?? "N/A";
                    var    connectMessage = new DynamicJsonValue
                    {
                        ["Id"]           = id,
                        ["ResourceName"] = resourceName,
                        ["Timeout"]      = timeout
                    };

                    var stream = new MemoryStream();

                    JsonOperationContext context;
                    using (_jsonContextPool.AllocateOperationContext(out context))
                        using (var writer = new BlittableJsonTextWriter(context, stream))
                        {
                            context.Write(writer, connectMessage);
                            writer.Flush();

                            ArraySegment <byte> bytes;
                            stream.TryGetBuffer(out bytes);
                            await client.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None)
                            .ConfigureAwait(false);
                        }

                    var requestsCounter = 0;
                    using (var fileStream = File.Create(config.RecordFilePath))
                    {
                        Stream finalStream = fileStream;
                        if (config.IsCompressed)
                        {
                            finalStream = new GZipStream(fileStream, CompressionMode.Compress, leaveOpen: true);
                        }

                        using (var streamWriter = new StreamWriter(finalStream))
                        {
                            var jsonWriter = new JsonTextWriter(streamWriter)
                            {
                                Formatting = Formatting.Indented
                            };
                            jsonWriter.WriteStartArray();
                            var sp = Stopwatch.StartNew();

                            while (true)
                            {
                                using (var reader = await Receive(client, context))
                                {
                                    if (reader == null)
                                    {
                                        // server asked to close connection
                                        break;
                                    }

                                    string type;
                                    if (reader.TryGet("Type", out type))
                                    {
                                        if (type.Equals("Heartbeat"))
                                        {
                                            continue;
                                        }
                                    }

                                    string error;
                                    if (reader.TryGet("Error", out error))
                                    {
                                        throw new InvalidOperationException("Server returned error: " + error);
                                    }

                                    var notification = new TrafficWatchNotification();
                                    notification.TimeStamp           = GetDateTimeFromJson(reader, "TimeStamp");
                                    notification.RequestId           = GetIntFromJson(reader, "RequestId");
                                    notification.HttpMethod          = GetStringFromJson(reader, "HttpMethod");
                                    notification.ElapsedMilliseconds = GetIntFromJson(reader, "ElapsedMilliseconds");
                                    notification.ResponseStatusCode  = GetIntFromJson(reader, "ResponseStatusCode");
                                    notification.TenantName          = GetStringFromJson(reader, "TenantName");
                                    notification.CustomInfo          = GetStringFromJson(reader, "CustomInfo");
                                    notification.InnerRequestsCount  = GetIntFromJson(reader, "InnerRequestsCount");
                                    // notification.QueryTimings = GetRavenJObjectFromJson(reader, "QueryTimings"); // TODO (TrafficWatch) : Handle this both server and client sides

                                    if (config.PrintOutput)
                                    {
                                        Console.Write("\rRequest #{0} Stored...\t\t ", ++requestsCounter);
                                    }

                                    var jobj = RavenJObject.FromObject(notification);
                                    jobj.WriteTo(jsonWriter);

                                    if (sp.ElapsedMilliseconds > 5000)
                                    {
                                        streamWriter.Flush();
                                        sp.Restart();
                                    }
                                }
                            }
                            jsonWriter.WriteEndArray();
                            streamWriter.Flush();
                            if (config.IsCompressed)
                            {
                                finalStream.Dispose();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("\r\n\nError while reading messages from server : " + ex);
                }
                finally
                {
                    Console.WriteLine("\r\n\nClosing connection to server...`");
                    try
                    {
                        await
                        client.CloseAsync(WebSocketCloseStatus.NormalClosure, "CLOSE_NORMAL", CancellationToken.None)
                        .ConfigureAwait(false);
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }
        }
Ejemplo n.º 10
0
        public async Task <string> AuthenticateAsync(string url, string apiKey, JsonOperationContext context)
        {
            var uri = new Uri(url.ToWebSocketPath());

            using (var webSocket = new RavenClientWebSocket())
            {
                try
                {
                    if (Logger.IsInfoEnabled)
                    {
                        Logger.Info($"Trying to connect using WebSocket to {uri} for authentication");
                    }
                    try
                    {
                        await webSocket.ConnectAsync(uri, _disposedToken.Token);
                    }
                    catch (WebSocketException webSocketException)
                    {
                        throw new InvalidOperationException($"Cannot connect using WebSocket to {uri} for authentication", webSocketException);
                    }

                    AuthenticatorChallenge authenticatorChallenge;
                    using (var result = await Recieve(webSocket, context))
                    {
                        if (result == null)
                        {
                            throw new InvalidDataException("Got null authtication challenge");
                        }
                        authenticatorChallenge = JsonDeserializationClient.AuthenticatorChallenge(result);
                    }
                    var challenge = ComputeChallenge(authenticatorChallenge, apiKey);
                    await Send(webSocket, context, "ChallengeResponse", challenge);

                    string currentToken;
                    using (var reader = await Recieve(webSocket, context))
                    {
                        string error;
                        if (reader.TryGet("Error", out error))
                        {
                            string exceptionType;
                            if (reader.TryGet("ExceptionType", out exceptionType) == false || exceptionType == "InvalidOperationException")
                            {
                                throw new InvalidOperationException("Server returned error: " + error);
                            }

                            if (exceptionType == "InvalidApiKeyException")
                            {
                                throw new InvalidApiKeyException(error);
                            }
                        }

                        string currentOauthToken;
                        if (reader.TryGet("CurrentToken", out currentOauthToken) == false || currentOauthToken == null)
                        {
                            throw new InvalidOperationException("Missing 'CurrentToken' in response message");
                        }

                        currentToken = currentOauthToken;
                    }

                    try
                    {
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close from client", _disposedToken.Token);
                    }
                    catch (Exception ex)
                    {
                        if (Logger.IsInfoEnabled)
                        {
                            Logger.Info("Failed to close the client", ex);
                        }
                    }

                    return(currentToken);
                }
                catch (Exception ex)
                {
                    if (Logger.IsInfoEnabled)
                    {
                        Logger.Info($"Failed to DoOAuthRequest to {url} with {apiKey}", ex);
                    }
                    throw;
                }
            }
        }