internal override bool OnAsyncResultReceived(AsyncReceiveBuffer result) { try { var dgram = HttpDatagram.Parse(result.Buffer); if (dgram == null || dgram.Type != HttpDatagramType.MSearch) { return(true); } var st = dgram.Headers.Get("ST"); var mx = dgram.Headers.Get("MX"); var man = dgram.Headers.Get("Man"); if (string.IsNullOrEmpty(st) || string.IsNullOrEmpty(mx) || man != Protocol.SsdpDiscoverMan) { return(true); } server.RequestRecieved(new Request(result.SenderIPEndPoint, st, UInt16.Parse(mx))); } catch (Exception e) { Log.Exception("Invalid HTTPMU/M-SEARCH datagram", e); } return(true); }
public bool Update(string usn, HttpDatagram dgram) { lock (mutex) { BrowseService service; if (!Services.TryGetValue(usn, out service)) { return(false); } timeouts.Remove(service.TimeoutId); service.Update(dgram, true); service.TimeoutId = timeouts.Add(service.Expiration, TimeoutHandler, service); client.CacheServiceUpdated(service); return(true); } }
internal override bool OnAsyncResultReceived(AsyncReceiveBuffer result) { try { HttpDatagram dgram = HttpDatagram.Parse(result.Buffer); if (dgram == null || dgram.Type != HttpDatagramType.Notify) { return(true); } string nts = dgram.Headers.Get("NTS"); string usn = dgram.Headers.Get("USN"); string nt = dgram.Headers.Get("NT"); if (String.IsNullOrEmpty(nts) || String.IsNullOrEmpty(usn)) { return(true); } if (!client.ServiceTypeRegistered(nt)) { return(true); } if (nts == Protocol.SsdpAliveNts) { try { if (!client.ServiceCache.Update(usn, dgram)) { client.ServiceCache.Add(new BrowseService(dgram, true)); } } catch (Exception e) { Log.Exception("Invalid ssdp:alive NOTIFY", e); } } else if (nts == Protocol.SsdpByeByeNts) { client.ServiceCache.Remove(usn); } } catch (Exception e) { Log.Exception("Invalid HTTPMU/NOTIFY datagram", e); } return(true); }
public static HttpDatagram Parse (byte [] rawDgram) { if (rawDgram.Length <= 0) { return null; } var headers_offset = 0; var type = DetectDatagramType (rawDgram, out headers_offset); if (type == HttpDatagramType.Unknown) { return null; } var dgram = new HttpDatagram (type); if (ParseHeaders (dgram, rawDgram, headers_offset)) { return dgram; } return null; }
private static bool ParseHeaders(HttpDatagram dgram, byte [] raw, int offset) { for (int i = offset, line_start = offset, sep_start = -1, n = raw.Length - 1; i < n; i++) { if (sep_start < 0 && raw[i] == ':') { // Account for the first : to denote the kvp split sep_start = i; } else if (raw[i] == '\r' && raw[i + 1] == '\n') { // Process on the line boundary int line_length = i - line_start - 1; int sep_length = sep_start - line_start; if (line_length > 0 && sep_length > 0) { // Encode the kvp string key = Encoding.ASCII.GetString(raw, line_start, sep_length); string value = Encoding.ASCII.GetString(raw, line_start + sep_length + 1, line_length - sep_length); // Save the header if (!String.IsNullOrEmpty(key)) { if (dgram.headers == null) { dgram.headers = new WebHeaderCollection(); } dgram.headers.Add(key.Trim(), value.Trim()); } } // Set state for next line line_start = i + 2; sep_start = -1; } } return(dgram.headers != null); }
internal void Update (HttpDatagram dgram, bool isGena) { if (isGena) { ServiceType = dgram.Headers.Get ("NT"); if (Client.StrictProtocol && String.IsNullOrEmpty (dgram.Headers.Get ("Host"))) { throw new ApplicationException ("Service did not send Host header"); } } else { ServiceType = dgram.Headers.Get ("ST"); if (Client.StrictProtocol && dgram.Headers.Get ("Ext") == null) { throw new ApplicationException ("Service did not send an Ext header " + "acknowledging 'Man: \"ssdp:discover\"' in request"); } } if (String.IsNullOrEmpty (ServiceType)) { throw new ApplicationException (String.Format ("Service did not send {0} header", isGena ? "NT" : "ST")); } Usn = dgram.Headers.Get ("USN"); if (String.IsNullOrEmpty (Usn)) { throw new ApplicationException ("Service did not send USN header"); } if (Client.StrictProtocol) { if (String.IsNullOrEmpty (dgram.Headers.Get ("Server"))) { throw new ApplicationException ("Service did not send Server header"); } if (String.IsNullOrEmpty (dgram.Headers.Get ("Server"))) { throw new ApplicationException ("Service did not send Server header"); } } ParseExpiration (dgram); ParseLocations (dgram); }
public static HttpDatagram Parse(byte [] rawDgram) { if (rawDgram.Length <= 0) { return(null); } var headers_offset = 0; var type = DetectDatagramType(rawDgram, out headers_offset); if (type == HttpDatagramType.Unknown) { return(null); } var dgram = new HttpDatagram(type); if (ParseHeaders(dgram, rawDgram, headers_offset)) { return(dgram); } return(null); }
public bool Update (string usn, HttpDatagram dgram) { lock (mutex) { BrowseService service; if (!Services.TryGetValue (usn, out service)) { return false; } timeouts.Remove (service.TimeoutId); service.Update (dgram, true); service.TimeoutId = timeouts.Add (service.Expiration, TimeoutHandler, service); client.CacheServiceUpdated (service); return true; } }
private static bool ParseHeaders(HttpDatagram dgram, byte [] raw, int offset) { for (int i = offset, line_start = offset, sep_start = -1, n = raw.Length - 1; i < n; i++) { if (sep_start < 0 && raw[i] == ':') { // Account for the first : to denote the kvp split sep_start = i; } else if (raw[i] == '\r' && raw[i + 1] == '\n') { // Process on the line boundary int line_length = i - line_start - 1; int sep_length = sep_start - line_start; if (line_length > 0 && sep_length > 0) { // Encode the kvp string key = Encoding.ASCII.GetString (raw, line_start, sep_length); string value = Encoding.ASCII.GetString (raw, line_start + sep_length + 1, line_length - sep_length); // Save the header if (!String.IsNullOrEmpty (key)) { if (dgram.headers == null) { dgram.headers = new WebHeaderCollection (); } dgram.headers.Add (key.Trim (), value.Trim ()); } } // Set state for next line line_start = i + 2; sep_start = -1; } } return dgram.headers != null; }
private void ParseLocations (HttpDatagram dgram) { ClearLocations (); string location = dgram.Headers.Get ("Location"); if (!String.IsNullOrEmpty (location)) { AddLocation (location); } string [] als = dgram.Headers.GetValues ("AL"); if (als != null) { foreach (string al in als) { AddLocation (al); } } if (LocationCount == 0) { throw new ApplicationException ("No Location/AL found in header"); } }
internal BrowseService (HttpDatagram dgram, bool isGena) { Update (dgram, isGena); }
private void ParseExpiration (HttpDatagram dgram) { // Prefer the "Cache-Control: max-age=SECONDS" directive string cc_max_age = dgram.Headers.Get ("Cache-Control"); if (!String.IsNullOrEmpty (cc_max_age)) { if (cc_max_age_regex == null) { cc_max_age_regex = new Regex (@"max-age\s*=\s*([0-9]+)", RegexOptions.IgnoreCase); } Match match = cc_max_age_regex.Match (cc_max_age); if (match.Success && match.Groups.Count == 2) { ushort expire = 0; if (UInt16.TryParse (match.Groups[1].Value, out expire)) { Expiration = DateTime.Now + TimeSpan.FromSeconds (expire); return; } } } // Fall back to possible Expires header string expires = dgram.Headers.Get ("Expires"); if (String.IsNullOrEmpty (expires)) { DateTime expire_date; if (DateTime.TryParse (expires, out expire_date)) { DateTime now = DateTime.Now; if (expire_date <= now || expire_date >= now.AddYears (1)) { Expiration = expire_date; return; } } } if (Client.StrictProtocol) { throw new ApplicationException ("Service does not specifiy a cache expiration"); } // Fall back to the default expiration value Expiration = DateTime.Now + TimeSpan.FromSeconds (Protocol.DefaultMaxAge); }