Example #1
0
    public void InputMessage(string message)
    {
        string      argument = "";
        UserCommand command  = null;

        foreach (UserCommand cmd in UserCommands)
        {
            if (message.Contains(cmd.CommandName))
            {
                command = cmd;

                string[] str = message.Split(char.Parse(" "));
                //Debug.Log("contains " + message + " LEN " + str.Length);
                //if(str.Length==2){
                //	for(int i = 1;i<str.Length;i++){
                //		argument += str[i];
                //	}
                //}
                //else {
                for (int i = 1; i < str.Length - 1; i++)
                {
                    argument += str[i] + " ";
                }
                argument += str[str.Length - 1];
                //}
            }
        }
        if (command == null)
        {
            //do message
            OutputMessage.Invoke(message);
        }
        else
        {
            //do command
            //Debug.Log("function " + command.CommandName + " argument " + argument,gameObject);
            command.Command.Invoke(argument);
            OutputCommand.Invoke(command.CommandName + " " + argument);
        }
    }
        /// <summary>
        /// Receives messages from debugger, parses them to extract the body, and dispatches them to <see cref="OutputMessage"/> listeners.
        /// </summary>
        private async void ReceiveAndDispatchMessagesWorker()
        {
            LiveLogger.WriteLine("Established connection.", typeof(DebuggerConnection));

            INetworkClient networkClient;

            lock (_networkClientLock) {
                networkClient = _networkClient;
            }
            if (networkClient == null)
            {
                return;
            }

            try {
                var stream = networkClient.GetStream();

                // Use a single read buffer and a single StringBuilder (periodically cleared) across loop iterations,
                // to avoid costly repeated allocations.
                var buffer = new byte[0x1000];
                var sb     = new StringBuilder();

                // Read and process incoming messages until disconnected.
                while (true)
                {
                    // Read the header of this message.
                    int contentLength = 0;
                    while (true)
                    {
                        // Read a single header field.
                        string field;
                        sb.Clear();
                        while (true)
                        {
                            int bytesRead = await stream.ReadAsync(buffer, 0, 1).ConfigureAwait(false);

                            if (bytesRead < 1)
                            {
                                // End of stream - we are disconnected from debuggee.
                                throw new EndOfStreamException();
                            }

                            var ch = (char)buffer[0];
                            if (ch == ':')
                            {
                                field = sb.ToString();
                                break;
                            }
                            sb.Append(ch);
                        }

                        // Blank line terminates the header.
                        if (string.IsNullOrEmpty(field))
                        {
                            break;
                        }

                        int.TryParse(field, out contentLength);
                        break;
                    }

                    if (contentLength == 0)
                    {
                        continue;
                    }

                    // Read the body of this message.

                    // If our preallocated buffer is large enough, use it - this should be true for vast majority of messages.
                    // If not, allocate a buffer that is large enough and use that, then throw it away - don't replace the original
                    // buffer with it, so that we don't hold onto a huge chunk of memory for the rest of the debugging session just
                    // because of a single long message.
                    var bodyBuffer = buffer.Length >= contentLength ? buffer : new byte[contentLength];

                    for (int i = 0; i < contentLength;)
                    {
                        i += await stream.ReadAsync(bodyBuffer, i, contentLength - i).ConfigureAwait(false);
                    }

                    string message = _encoding.GetString(bodyBuffer, 0, contentLength);
                    LiveLogger.WriteLine("Response: " + message, typeof(DebuggerConnection));

                    // Notify subscribers.
                    OutputMessage?.Invoke(this, new MessageEventArgs(message));
                }
            } catch (SocketException) {
            } catch (IOException) {
            } catch (ObjectDisposedException) {
            } catch (InvalidOperationException) {
            } catch (DecoderFallbackException ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error decoding response body: {0}", ex), typeof(DebuggerConnection));
            } catch (JsonReaderException ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error parsing JSON response: {0}", ex), typeof(DebuggerConnection));
            } catch (Exception ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Message processing failed: {0}", ex), typeof(DebuggerConnection));
                //throw;
            } finally {
                LiveLogger.WriteLine("Connection was closed.", typeof(DebuggerConnection));

                ConnectionClosed?.Invoke(this, EventArgs.Empty);
            }
        }
Example #3
0
 private static void HandMessage(string format, params object[] args)
 {
     OutputMessage?.Invoke(string.Format(format, args));
 }
Example #4
0
 private static void HandMessage(object Msg, Exception ex)
 {
     OutputMessage?.Invoke(string.Format("{0}:{1}", Msg.ToString(), ex.ToString()));
 }
Example #5
0
 private static void HandMessage(object Msg)
 {
     OutputMessage?.Invoke(Msg.ToString());
 }
Example #6
0
        /// <summary>
        /// Receives messages from debugger, parses them to extract the body, and dispatches them to <see cref="OutputMessage"/> listeners.
        /// </summary>
        private async void ReceiveAndDispatchMessagesWorker()
        {
            LiveLogger.WriteLine("Established connection.", typeof(DebuggerConnection));

            INetworkClient networkClient;

            lock (_networkClientLock) {
                networkClient = _networkClient;
            }
            if (networkClient == null)
            {
                return;
            }

            try {
                var stream = networkClient.GetStream();

                // Use a single read buffer and a single StringBuilder (periodically cleared) across loop iterations,
                // to avoid costly repeated allocations.
                var buffer = new byte[0x1000];
                var sb     = new StringBuilder();

                // Read and process incoming messages until disconnected.
                while (true)
                {
                    // Read the header of this message.
                    int contentLength = 0;
                    while (true)
                    {
                        // Read a single header field.
                        string field;
                        sb.Clear();
                        while (true)
                        {
                            int bytesRead = await stream.ReadAsync(buffer, 0, 1).ConfigureAwait(false);

                            if (bytesRead < 1)
                            {
                                // End of stream - we are disconnected from debuggee.
                                throw new EndOfStreamException();
                            }

                            // All fields that we care about are ASCII, and for all the other fields we only need to recognize
                            // the trailing \r\n, so there's no need to do proper decoding here.
                            sb.Append((char)buffer[0]);

                            // "\r\n" terminates the field.
                            if (sb.Length >= 2 && sb[sb.Length - 2] == '\r' && sb[sb.Length - 1] == '\n')
                            {
                                field = sb.ToString(0, sb.Length - 2);
                                break;
                            }
                        }

                        // Blank line terminates the header.
                        if (string.IsNullOrEmpty(field))
                        {
                            break;
                        }

                        // Otherwise, it's an actual field. Parse it if it's something we care about.

                        // Content-Length
                        var match = _contentLengthFieldRegex.Match(field);
                        if (match.Success)
                        {
                            int.TryParse(match.Groups[1].Value, out contentLength);
                            continue;
                        }

                        // Embedding-Host, which contains the Node.js version number. Only try parsing that if we don't know the version yet -
                        // it normally comes in the very first packet, so this saves time trying to parse all the consequent ones.
                        if (NodeVersion == null)
                        {
                            match = _nodeVersionFieldRegex.Match(field);
                            if (match.Success)
                            {
                                Version nodeVersion;
                                Version.TryParse(match.Groups[1].Value, out nodeVersion);
                                _nodeVersion = nodeVersion;
                            }
                        }
                    }

                    if (contentLength == 0)
                    {
                        continue;
                    }

                    // Read the body of this message.

                    // If our preallocated buffer is large enough, use it - this should be true for vast majority of messages.
                    // If not, allocate a buffer that is large enough and use that, then throw it away - don't replace the original
                    // buffer with it, so that we don't hold onto a huge chunk of memory for the rest of the debugging session just
                    // because of a single long message.
                    var bodyBuffer = buffer.Length >= contentLength ? buffer : new byte[contentLength];

                    for (int i = 0; i < contentLength;)
                    {
                        i += await stream.ReadAsync(bodyBuffer, i, contentLength - i).ConfigureAwait(false);
                    }

                    string message = _encoding.GetString(bodyBuffer, 0, contentLength);
                    LiveLogger.WriteLine("Response: " + message, typeof(DebuggerConnection));

                    // Notify subscribers.
                    OutputMessage?.Invoke(this, new MessageEventArgs(message));
                }
            } catch (SocketException) {
            } catch (IOException) {
            } catch (ObjectDisposedException) {
            } catch (InvalidOperationException) {
            } catch (DecoderFallbackException ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error decoding response body: {0}", ex), typeof(DebuggerConnection));
            } catch (JsonReaderException ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error parsing JSON response: {0}", ex), typeof(DebuggerConnection));
            } catch (Exception ex) {
                LiveLogger.WriteLine(string.Format(CultureInfo.InvariantCulture, "Message processing failed: {0}", ex), typeof(DebuggerConnection));
                throw;
            } finally {
                LiveLogger.WriteLine("Connection was closed.", typeof(DebuggerConnection));

                ConnectionClosed?.Invoke(this, EventArgs.Empty);
            }
        }