// Reads our packet buffer queue if there is any data to be read private void ReadPacketBuffer() { // Create a wait handle so we only process data as it's sent to us WaitHandle[] wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(wait)) { // Lock our incoming data queue to prevent race conditions lock (IncomingBufferQueue) { // Check if there is data waiting if (IncomingBufferQueue.Count > 0) { // Get data from queue var Data = IncomingBufferQueue.Dequeue(); // Process this data ProcessBuffer(Data); } // There is not incoming data else { // No data to be read, reset our ready event ReadyEvent.Reset(); continue; } } } }
// Handles writing anything in our write queue private void ProcessCommand() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait) && Connection.State == ConnectionState.Open) { // Lock our data queue to prevent race conditions lock (WriteQueue) { // Data queue has entries if (WriteQueue.Count > 0) { // Dequeue next piece of Data in line var Data = WriteQueue.Dequeue(); // Handle this data Data.ExecuteNonQuery(); } // There are no entries in the data queue else { // No data in line, reset ready event ReadyEvent.Reset(); continue; } } } }
// Accepts new connection contexts private void AcceptContext() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait)) { // Lock our context queue to prevent race conditions lock (ContextQueue) { // Context queue has entries, accept one if (ContextQueue.Count > 0) { // Dequeue next context in line var Context = ContextQueue.Dequeue(); // Handle this context HandleRequest(Context); } // There are no entries in the connection queue else { // No context in line, reset ready event ReadyEvent.Reset(); continue; } } } }
public override void Close() { Send(new ShutdownTcpAckMessage()); base.Close(); if (EncryptContext != null) { EncryptContext.Dispose(); EncryptContext = null; } ReadyEvent.Reset(); }
// Accepts incoming connections if we are able private void AcceptPeerConnection() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait)) { // Check if stopped if (StopEvent.WaitOne(0)) { break; } // Lock our connection queue to prevent any race conditions lock (ConnectionQueue) { // Connection queue has entries, accept one if (ConnectionQueue.Count > 0) { // Dequeue the new peer in line var Connection = ConnectionQueue.Dequeue(); // Create a peer instance var Peer = new P2pPeer(this, Connection, PeerDirection.IN); // Handle this connection AddPeer(Peer); } // There are no entries in the connection queue else { // No peers in line, reset ready event ReadyEvent.Reset(); continue; } } } }
// Writes a log message to the console, as well as to an optional log file // TODO - this is kind of a monolith, it could probably be shortened private void Write() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait)) { // Check if we need to stop and ignore queue if (StopEvent.WaitOne(0) && IgnoreQueue) { break; } // Lock the message queue to prevent race conditions lock (MessageQueue) { // Check if there are any messages in the queue if (MessageQueue.Count == 0) { ReadyEvent.Reset(); continue; } // Dequeue a message var Message = MessageQueue.Dequeue(); // Check if logging is enabled if (LogLevel <= LogLevel.NONE) { // Reset ready event ReadyEvent.Reset(); continue; } // Create an output string builder StringBuilder Output = new StringBuilder(Message.Message); // Add time and label prefix StringBuilder Prefix = new StringBuilder(""); if (Message.Prefix) { // Add time if (LogLevel >= LogLevel.MAX) { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss.ffffff")} ["); } else if (LogLevel >= LogLevel.DEBUG) { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss.ff")} ["); } else { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss")} ["); } // Add custom prefix if (!string.IsNullOrEmpty(CustomPrefix)) { Prefix.Append($"{CustomPrefix} "); } // Add label if (Message.Label != LogLabel.IMPORTANT) { Prefix.Append($"{Message.Label}]"); } else { Prefix.Append($"{LogLabel.INFO}]"); } // Pad prefix if (LogLevel >= LogLevel.MAX) { Prefix.Append(' ', 37 - Prefix.Length); } else if (LogLevel >= LogLevel.DEBUG) { Prefix.Append(' ', 33 - Prefix.Length); } else { Prefix.Append(' ', 30 - Prefix.Length); } if (!string.IsNullOrEmpty(CustomPrefix)) { Prefix.Append(' '); } } Output.Insert(0, Prefix); // Set console color switch (Message.Label) { case LogLabel.IMPORTANT: Console.ForegroundColor = ImportantColor; break; case LogLabel.INFO: Console.ForegroundColor = InfoColor; break; case LogLabel.ERROR: Console.ForegroundColor = ErrorColor; break; case LogLabel.WARNING: Console.ForegroundColor = WarningColor; break; case LogLabel.DEBUG: Console.ForegroundColor = DebugColor; break; } // Write to console Console.WriteLine(Output); // Append to log file if (!string.IsNullOrEmpty(LogFile)) { try { File.AppendAllText(LogFile, $"{Output}\n"); } catch { } } // Set console color back to default Console.ForegroundColor = ConsoleColor.Gray; } } }