public MainForm() { InitializeComponent(); this.Text += " " + Globals.AssemblyVersion; try { cbStartAutomatically.Checked = CheckAutomaticStartup(); } catch (Exception) { MessageBox.Show("Insufficient permission to access Task Scheduler."); } nudHttpPort.Value = Program.settings.http_port; nudHttpsPort.Value = Program.settings.https_port; nudIdleMs.Value = Program.settings.idleTimeMs; nudInputsRequiredToWake.Value = Program.settings.inputsRequiredToWake; txtIpWhitelist.Text = Program.settings.GetIpWhitelistString(); txtSyncAddress.Text = Program.settings.syncAddress; nudSyncPort.Value = Program.settings.syncPort; ddlSyncFailureAction.SelectedIndex = BPMath.Clamp(Program.settings.syncFailureAction, 0, 2); cbSyncHTTPS.Checked = Program.settings.syncHTTPS; cbSyncMuteWhenOff.Checked = Program.settings.syncMute; cbAllowLocalOverride.Checked = Program.settings.syncAllowLocalOverride; SetCurrentHttpPorts(); }
private void streamLoop_inner(object objArgs) { Stopwatch frameTimer = new Stopwatch(); frameTimer.Start(); long nextFrameStart = 0; StreamThreadArgs args = (StreamThreadArgs)objArgs; while (!args.abortFlag.abort) { try { int sleepTime = (int)(nextFrameStart - frameTimer.ElapsedMilliseconds); while (sleepTime > 0 || (Interlocked.Read(ref args.numSentFrames) >= Interlocked.Read(ref args.numAcknowledgedFrames) + maxUnacknowledgedFrames)) { if (args.abortFlag.abort) { return; } Thread.Sleep(BPMath.Clamp(sleepTime, 1, 10)); sleepTime = (int)(nextFrameStart - frameTimer.ElapsedMilliseconds); } if (args.abortFlag.abort) { return; } nextFrameStart = frameTimer.ElapsedMilliseconds + (1000 / maxFPS); if (streamerController == null) { return; } FragmentedImage fragmentedImage = streamerController.GetRawDesktopCapture(imgFlags, jpegQuality, args.abortFlag); if (args.abortFlag.abort) { return; } if (fragmentedImage == null) { fragmentedImage = new FragmentedImage(); } fragmentedImage.streamId = (byte)args.myStreamNumber; using (MemoryDataStream mds = new MemoryDataStream(fragmentedImage.GetMaximumRequiredBufferSize())) { byte[] compressionBuffer = null; fragmentedImage.WriteToDataStream(mds, ref compressionBuffer); Interlocked.Increment(ref args.numSentFrames); Send(mds.ToArray()); } } catch (ThreadAbortException) { throw; } catch (Exception ex) { Logger.Debug(ex); } } }
private void StopStreaming(int waitMs = 10000) { streamThreadArgs.abortFlag.abort = true; if (streamingThread != null) { Interlocked.Increment(ref activeStreamNumber); if (waitMs < 1 || !streamingThread.Join(BPMath.Clamp(waitMs, 1000, 60000))) { streamingThread.Abort(); } streamingThread = null; } }
/// <summary> /// Calls Application.Exit(), but leaves a background thread running which will kill the current process after a delay if Application.Exit() fails to do so in that time. /// </summary> /// <param name="msBeforeKill"></param> private static void RobustExit(int msBeforeKill = 1000) { Thread thrKillProc = new Thread(() => { Try.Swallow(() => { Thread.Sleep(BPMath.Clamp(msBeforeKill, 0, 60000)); }); Try.Swallow(() => { Process.GetCurrentProcess()?.Kill(); }); }); thrKillProc.Name = "Kill Process After 1 Second"; thrKillProc.IsBackground = true; thrKillProc.Start(); Application.Exit(); }
/// <summary> /// Sends the specified iTachCmd and returns null upon success, or the response string or other error message if the iTach returned an error response. May throw an exception if there is a network error. /// </summary> /// <param name="cmd">The command to send.</param> /// <param name="connectorAddress">The connector address. If null, the address specified in the command will be used.</param> /// <param name="repeat">(Optional, 1-50) Number of times the iTach should repeat the command.</param> /// <returns></returns> public string SendCommandSync(iTachCmd cmd, string connectorAddress, byte?repeat = null) { if (string.IsNullOrWhiteSpace(host)) { return("This iTachController does not have the host specified."); } lock (myLock) { ushort myId = idCounter++; if (repeat == null) { repeat = cmd.Repeat; } repeat = BPMath.Clamp(repeat.Value, (byte)1, (byte)50); // 50 is iTach's built-in limit if (connectorAddress == null) { connectorAddress = cmd.ConnectorAddress; } else if (!Regex.IsMatch(connectorAddress, "^\\d+:\\d+$")) { Logger.Debug("iTach effect specified invalid connector address \"" + connectorAddress + "\""); connectorAddress = cmd.ConnectorAddress; } string commandText = "sendir," + connectorAddress + "," + myId + "," + cmd.Frequency + "," + repeat + "," + cmd.RepeatOffset + "," + string.Join(",", cmd.Codes) + "\r"; string expectedResponse = "completeir," + connectorAddress + "," + myId + "\r"; byte[] buff = Encoding.ASCII.GetBytes(commandText); using (TcpClient client = new TcpClient(host, GetPort())) { using (NetworkStream stream = client.GetStream()) { stream.Write(buff, 0, buff.Length); StringBuilder sb = new StringBuilder(); int i; while ((i = stream.ReadByte()) != -1) { char c = (char)i; sb.Append(c); if (c == '\r') { break; } } string response = sb.ToString(); return(response == expectedResponse ? null : response); } } } }
public static byte[] Encode(byte[] rgb, int width, int height, int quality) { using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb)) { BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); Marshal.Copy(rgb, 0, bitmapData.Scan0, rgb.Length); bmp.UnlockBits(bitmapData); using (MemoryStream ms = new MemoryStream()) { ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg); EncoderParameters parameters = new EncoderParameters(1); parameters.Param[0] = new EncoderParameter(Encoder.Quality, BPMath.Clamp(quality, 1, 100)); bmp.Save(ms, jpgEncoder, parameters); return(ms.ToArray()); } } }
private static void PartialWakeLogic(bool mute, int totalInputs = 1, PartialWakeNotifier pwn = null, int iterations = 0) { double inputsRequired = BPMath.Clamp(Program.settings.inputsRequiredToWake, 1, 50); const int maxIterations = 100; const int iterationInterval = 100; if (totalInputs >= inputsRequired) { // Input requirements met. Full Wake. if (pwn != null) { pwn.Terminate(); } } else if (iterations < maxIterations) { // Waiting for more inputs. if (pwn == null) { pwn = new PartialWakeNotifier(); pwn.Progress = (int)((totalInputs / inputsRequired) * 100); SetTimeout.OnBackground(() => { Application.Run(pwn); }, 0); } pwn.SetSecondsRemaining((int)(((maxIterations - iterations) * iterationInterval) / 1000.0)); SetTimeout.OnBackground(() => { if (LastInput.GetLastInputAgeMs() < maxIterations) { totalInputs++; pwn.Progress = (int)((totalInputs / inputsRequired) * 100); } PartialWakeLogic(mute, totalInputs, pwn, iterations + 1); }, iterationInterval); } else { // Input requires not met. Go back to sleep. if (pwn != null) { pwn.Terminate(); } Off(mute); } }
protected override void OnMessage(MessageEventArgs e) { if (!e.IsBinary) { CloseSocket(); return; } byte[] buf = e.RawData; if (buf.Length == 0) { CloseSocket(); return; } Command cmd = (Command)buf[0]; try { switch (cmd) { case Command.StartStreaming: if (buf.Length < 3) { SyntaxError(buf[0], buf); break; } StopStreaming(); Console.WriteLine(ID + " Command.StartStreaming " + (byte)Interlocked.Read(ref activeStreamNumber)); Send(new byte[] { buf[0], (byte)Interlocked.Read(ref activeStreamNumber) }); StartStreaming(buf); break; case Command.StopStreaming: Console.WriteLine(ID + " Command.StopStreaming"); StopStreaming(); break; case Command.AcknowledgeFrame: if (buf.Length < 2) { SyntaxError(buf[0], buf); break; } AcknowledgeFrame(buf[1]); break; case Command.ReproduceUserInput: if (buf.Length < 2) { SyntaxError(buf[0], buf); break; } InputType inputType = (InputType)buf[1]; if (inputType == InputType.KeyDown || inputType == InputType.KeyUp) { if (buf.Length < 10) { SyntaxError(buf[0], buf, inputType); break; } int keyCode = ByteUtil.ReadInt32(buf, 2); ModifierKeys modifiers = (ModifierKeys)ByteUtil.ReadUInt32(buf, 6); streamerController.DoKeyboardInput(keyCode, modifiers, inputType == InputType.KeyUp); } else if (inputType == InputType.MouseMove) { if (buf.Length < 10) { SyntaxError(buf[0], buf, inputType); break; } float x = ByteUtil.ReadFloat(buf, 2); float y = ByteUtil.ReadFloat(buf, 6); streamerController.DoMouseMove(x, y); } else if (inputType == InputType.MouseButtonDown || inputType == InputType.MouseButtonUp) { if (buf.Length < 3) { SyntaxError(buf[0], buf, inputType); break; } MouseButton button = (MouseButton)buf[2]; streamerController.DoMouseButton(button, inputType == InputType.MouseButtonUp); } else if (inputType == InputType.MouseWheel) { if (buf.Length < 6) { SyntaxError(buf[0], buf, inputType); break; } short deltaX = ByteUtil.ReadInt16(buf, 2); short deltaY = ByteUtil.ReadInt16(buf, 4); streamerController.DoMouseWheel(deltaX, deltaY); } break; case Command.GetDesktopInfo: DesktopInfo desktopInfo = streamerController.GetDesktopInfo(); using (MemoryDataStream mds = new MemoryDataStream()) { desktopInfo.WriteToDataStream(mds); Send(mds.ToArray()); } break; case Command.SetStreamSettings: if (buf.Length < 5) { SyntaxError(buf[0], buf); break; } imgFlags = (ImgFlags)buf[1]; jpegQuality = BPMath.Clamp <byte>(buf[2], 1, 100); maxFPS = BPMath.Clamp <byte>(buf[3], 1, byte.MaxValue); maxUnacknowledgedFrames = BPMath.Clamp <byte>(buf[4], 1, byte.MaxValue); break; case Command.GetStreamSettings: byte[] response = new byte[4]; response[0] = buf[0]; response[1] = (byte)imgFlags; response[2] = jpegQuality; response[3] = maxFPS; Send(response); break; case Command.KeepAlive: break; default: // CloseSocket(); Send(new byte[] { (byte)Command.Error_CommandCodeUnknown }); break; } } catch (ThreadAbortException) { throw; } catch (Exception ex) { Logger.Debug(ex, "WebSocketServer"); } }
private void BwSpeedTestController_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker self = (BackgroundWorker)e.Argument; int testDurationSeconds = Program.config.testDurationSeconds; // Open Control Connection using (TcpClient controlConnection = new TcpClient(remoteHost, remoteTcpPort)) using (Stream controlStream = controlConnection.GetStream()) { self.ReportProgress(0, new { DataType = 'D', Bytes = 0, Index = 0 }); self.ReportProgress(0, new { DataType = 'U', Bytes = 0, Index = 0 }); ByteUtil.WriteUtf8("STSCC0", controlStream); controlStream.WriteByte((byte)Program.config.testDirection); string key = ByteUtil.ReadUtf8_16(controlStream); ControlConnectionContext control = new ControlConnectionContext(controlConnection, disconnectedControl => { }, key); control.testDirection = Program.config.testDirection; long lastBytesRead = 0; int dlReportIdx = 0; control.speedReport = (bytesReadSoFar) => { if (self.CancellationPending) { return; } long bytesNew = bytesReadSoFar - Interlocked.Exchange(ref lastBytesRead, bytesReadSoFar); int idx = Interlocked.Increment(ref dlReportIdx); self.ReportProgress(0, new { DataType = 'D', Bytes = bytesNew, Index = idx }); }; control.StartBandwidthMeasurement(); Stopwatch sw = Stopwatch.StartNew(); int numStreams = BPMath.Clamp(Program.config.tcpTestStreams, 1, 1000); for (int i = 0; i < numStreams; i++) { TcpTestConnectionClient.OpenTestConnection(control, testDurationSeconds); } bool isDownloading = control.testDirection == 0 || control.testDirection == 2; bool isUploading = control.testDirection == 1 || control.testDirection == 2; // Begin reading speed reports from the remote client. These are our upload speed reports. int expectedNumSpeedReports = testDurationSeconds * 10; if (isUploading) { long lastBytesWritten = 0; for (int ulReportIdx = 0; ulReportIdx < expectedNumSpeedReports; ulReportIdx++) { if (self.CancellationPending) { return; } long bytesWritten = ByteUtil.ReadInt64(controlStream); long bytesNew = bytesWritten - lastBytesWritten; lastBytesWritten = bytesWritten; self.ReportProgress(0, new { DataType = 'U', Bytes = bytesNew, Index = ulReportIdx + 1 }); } } while (isDownloading && dlReportIdx < expectedNumSpeedReports && ((testDurationSeconds * 1200) - sw.ElapsedMilliseconds > 0)) { if (self.CancellationPending) { return; } Thread.Sleep(10); } } }
/// <summary> /// Begins listening to all hardware keyboards. /// </summary> /// <param name="msBetweenKeyboardScans">The rescan interval in milliseconds. This interval shouldn't be extremely small, for efficiency's sake, as it creates new processes and whatnot to perform the scans.</param> public AllKeyboardListener(int msBetweenKeyboardScans = 5000) { this.msBetweenKeyboardScans = BPMath.Clamp(msBetweenKeyboardScans, 1000, (int)TimeSpan.FromDays(1).TotalSeconds); ScanForNewKeyboards(); }
public override void handleGETRequest(HttpProcessor p) { string pageLower = p.requestedPage.ToLower(); if (p.requestedPage == "randomdata") { p.writeSuccess("application/x-binary"); p.outputStream.Flush(); int testSec = p.GetIntParam("testsec", 5); testSec = BPMath.Clamp(testSec, 1, 30); long endTime = sw.ElapsedMilliseconds + (long)TimeSpan.FromSeconds(testSec).TotalMilliseconds; byte[] randomData = StaticRandom.NextBytes(p.tcpClient.SendBufferSize); while (sw.ElapsedMilliseconds < endTime) { p.tcpStream.Write(randomData, 0, randomData.Length); } } else if (p.requestedPage == "nstws") { wss.AcceptIncomingConnection(p.tcpClient); } else if (p.requestedPage == "HEADERS") { p.writeSuccess("text/plain"); p.outputStream.Write(string.Join(Environment.NewLine, p.httpHeadersRaw.Select(h => h.Key + ": " + h.Value))); } else if (p.requestedPage == "IP") { p.writeSuccess("text/plain"); p.outputStream.Write(p.RemoteIPAddressStr); } else { if (p.requestedPage == "") { p.requestedPage = "default.html"; } string wwwPath = Globals.ApplicationDirectoryBase + "www/"; #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { wwwPath = Globals.ApplicationDirectoryBase + "../../www/"; } #endif DirectoryInfo WWWDirectory = new DirectoryInfo(wwwPath); string wwwDirectoryBase = WWWDirectory.FullName.Replace('\\', '/').TrimEnd('/') + '/'; FileInfo fi = new FileInfo(wwwDirectoryBase + p.requestedPage); string targetFilePath = fi.FullName.Replace('\\', '/'); if (!targetFilePath.StartsWith(wwwDirectoryBase) || targetFilePath.Contains("../")) { p.writeFailure("400 Bad Request"); return; } if (!fi.Exists) { return; } if ((fi.Extension == ".html" || fi.Extension == ".htm") && fi.Length < 256000) { string html = File.ReadAllText(fi.FullName); html = html.Replace("%%VERSION%%", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()); html = html.Replace("%%RND%%", rnd.ToString()); byte[] data = Encoding.UTF8.GetBytes(html); p.writeSuccess(Mime.GetMimeType(fi.Extension), data.Length); p.outputStream.Flush(); p.tcpStream.Write(data, 0, data.Length); p.tcpStream.Flush(); } else { string mime = Mime.GetMimeType(fi.Extension); if (pageLower.StartsWith(".well-known/acme-challenge/")) { mime = "text/plain"; } if (fi.LastWriteTimeUtc.ToString("R") == p.GetHeaderValue("if-modified-since")) { p.writeSuccess(mime, -1, "304 Not Modified"); return; } p.writeSuccess(mime, fi.Length, additionalHeaders: GetCacheLastModifiedHeaders(TimeSpan.FromHours(1), fi.LastWriteTimeUtc)); p.outputStream.Flush(); using (FileStream fs = fi.OpenRead()) { fs.CopyTo(p.tcpStream); } p.tcpStream.Flush(); } } }
public static double BroadlinkPulseSizeToMicroSeconds(ushort pulseSize) { return(BPMath.Clamp(pulseSize * BroadlinkPulseDurationInMicroSeconds, (ushort)4, ushort.MaxValue)); // iTach requires an 80uS minimum time, which at 38000 KHz means a minimum value of 4. }
public static ushort MicroSecondsToBroadlinkPulseSize(double microSeconds) { return(BPMath.Clamp((ushort)Math.Round(microSeconds / BroadlinkPulseDurationInMicroSeconds), (ushort)1, ushort.MaxValue)); }