Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
 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;
 }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
 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;
     }
 }
Ejemplo n.º 9
0
        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;
        }
Ejemplo n.º 10
0
 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");
     }
 }
Ejemplo n.º 11
0
 internal BrowseService (HttpDatagram dgram, bool isGena)
 {
     Update (dgram, isGena);    
 }
Ejemplo n.º 12
0
 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);
 }