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); } }
private static void HandMessage(string format, params object[] args) { OutputMessage?.Invoke(string.Format(format, args)); }
private static void HandMessage(object Msg, Exception ex) { OutputMessage?.Invoke(string.Format("{0}:{1}", Msg.ToString(), ex.ToString())); }
private static void HandMessage(object Msg) { OutputMessage?.Invoke(Msg.ToString()); }
/// <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); } }