using System; using System.Drawing; using System.IO; using System.Net; using System.Threading; using System.Threading.Tasks; namespace IPCamAppBar { public class FrameEventArgs : EventArgs { public Image Image { get; set; } } public delegate void FrameEvent(object sender, FrameEventArgs args); internal abstract class CameraStream : IDisposable { public event FrameEvent Frame; private readonly CancellationTokenSource cancelTaskTokenSource = new CancellationTokenSource(); private Task streamTask; protected CameraStream() { } public void Start(string url) { if (streamTask != null) throw new InvalidOperationException("CameraStream already started"); streamTask = Task.Run(() => Fetch(url, cancelTaskTokenSource.Token)); } public void Dispose() { cancelTaskTokenSource.Cancel(); streamTask?.Wait(); } private async Task Fetch(string url, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { var uri = new Uri(url); var request = WebRequest.CreateHttp(uri); if (!string.IsNullOrEmpty(uri.UserInfo)) { var parts = uri.UserInfo.Split(':'); request.Credentials = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : ""); } try { HttpWebResponse response; using (cancellationToken.Register(() => request.Abort(), false)) { response = (HttpWebResponse)await request.GetResponseAsync(); cancellationToken.ThrowIfCancellationRequested(); } if (response.StatusCode != HttpStatusCode.OK) throw new WebException(response.StatusDescription); using (var responseStream = response.GetResponseStream()) { await ReadFrames(responseStream, cancellationToken); } } catch (Exception e) { if (cancellationToken.IsCancellationRequested) break; // TODO onException await Task.Delay(5000, cancellationToken); } } } protected abstract Task ReadFrames(Stream stream, CancellationToken cancellationToken); protected virtual void OnFrame(FrameEventArgs args) { Frame?.Invoke(this, args); } } internal static class BufferExtensions { public static int Find(this byte[] buffer, byte[] pattern, int limit = int.MaxValue, int startAt = 0) { var patternIndex = 0; var bufferIndex = 0; for (bufferIndex = startAt; bufferIndex < buffer.Length && patternIndex < pattern.Length && bufferIndex < limit; bufferIndex++) { if (buffer[bufferIndex] == pattern[patternIndex]) { patternIndex++; } else { patternIndex = 0; } } if (patternIndex == pattern.Length) return bufferIndex - pattern.Length; return -1; } } }