public static SsdpDevice ParseBroadcastResponse(IPAddress endpoint, string data) { // parse http response header var pairs = data .Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Skip(1) .Select(line => line.Split(new[] { ":" }, 2, StringSplitOptions.None)) .Where(parts => parts.Length == 2) .ToDictionary(parts => parts[0].ToLowerInvariant().Trim(), parts => parts[1].Trim()); var device = new SsdpDevice(); device.RemoteEndPoint = endpoint; string location; if (pairs.TryGetValue("location", out location)) { UriBuilder uriBuilder = null; Uri uri = null; if (Uri.TryCreate(location, UriKind.Absolute, out uri)) { uriBuilder = new UriBuilder(uri); } else { uriBuilder = new UriBuilder(); uriBuilder.Host = location; uriBuilder.Scheme = "unknown"; } device.Location = uriBuilder.Uri; } else { return(null); } string server; if (pairs.TryGetValue("server", out server)) { device.Server = server; } string st; if (pairs.TryGetValue("st", out st)) { device.ServiceType = st; } string usn; if (pairs.TryGetValue("usn", out usn)) { device.UniqueServiceName = usn; } return(device); }
private async Task FetchDeviceInfo(SsdpDevice device, CancellationToken cancelToken) { try { var httpRequest = WebRequest.CreateHttp(device.Location); httpRequest.Timeout = (int)Math.Round(_replyWait.TotalMilliseconds); cancelToken.Register(() => { try { httpRequest.Abort(); } catch { } }); using (var response = (HttpWebResponse)(await httpRequest.GetResponseAsync())) { if (response.StatusCode == HttpStatusCode.OK) { using (var responseStream = response.GetResponseStream()) using (var responseReader = new StreamReader(responseStream, Encoding.UTF8)) { var data = await responseReader.ReadToEndAsync(); var deviceInfo = SsdpDeviceInfo.ParseDeviceResponse(data); device.Info = deviceInfo; } } } } catch (ArgumentException) { } catch (WebException) { } catch (SocketException) { } catch (ObjectDisposedException) { } catch (OperationCanceledException) { } catch (Exception ex) { #if DEBUG Console.WriteLine(ex); #endif } _deviceFoundCallback?.Invoke(device); }
private async Task ReceiveServicer(UdpClient client) { var endpoint = SSDP_RECEIVE_ENDPOINT; var replyWaitTask = _replyWait.TotalMilliseconds > 0 ? Task.Delay(_replyWait) : new TaskCompletionSource <object>().Task; List <Task> fetchDeviceInfoTasks = new List <Task>(); while (!_isCancelled && !replyWaitTask.IsCompleted) { try { var receiveTask = SafeReceiveAsync(client); var finishedTask = await Task.WhenAny(receiveTask, _cancelTask.Task, replyWaitTask); if (finishedTask == receiveTask) { var asyncResult = await receiveTask; if (asyncResult.Buffer == null) { continue; } var received = receiveTask.Result; if (received.Buffer != null && received.Buffer.Length > 0) { var responseData = Encoding.ASCII.GetString(received.Buffer, 0, received.Buffer.Length); var device = SsdpDevice.ParseBroadcastResponse(received.RemoteEndPoint.Address, responseData); if (device != null) { if (_foundLocations.TryAdd(device.Location, device)) { if (device.Location.Scheme != "unknown") { fetchDeviceInfoTasks.Add(FetchDeviceInfo(device, _cancelTokenSrc.Token)); } else { _deviceFoundCallback?.Invoke(device); } } } } } else { ObserveUdpTaskException(receiveTask); } } catch (SocketException) { } catch (ObjectDisposedException) { } catch (OperationCanceledException) { } catch (Exception ex) { #if DEBUG Console.WriteLine(ex); throw ex; #endif } } if (fetchDeviceInfoTasks.Count > 0) { await Task.WhenAll(fetchDeviceInfoTasks); } }