예제 #1
0
        }   // Discover

        public void OnReceive(IAsyncResult ar)
        // a reply has arrived...
        {
            UdpClient  client = (UdpClient)ar.AsyncState;
            IPEndPoint ep     = null;

            byte[] buf = client.EndReceive(ar, ref ep);     // get the response
            if (buf != null)
            {
                client.BeginReceive(new AsyncCallback(OnReceive), client);      // set up for another message to arrive
                try
                {
                    HTTPMessage msg = HTTPMessage.ParseByteArray(buf, 0, buf.Length);
                    // here filter to replies containing 'sonos' and add to zones..
                    if (msg.StringPacket.ToLower().Contains("sonos"))
                    {
                        string loc = msg.GetTag("Location");

                        if (!_zones.Contains(loc))
                        {
                            _zones.Add(loc);
                            _zoneTable.Add(loc, ""); // Will fill in zone friendly name later.
                        }
                    }
                }
                catch
                {
                    // a problem dealing with the reply message, so ignore it
                }
                return;
            }
        }       // OnReceive
예제 #2
0
        /// <summary>
        /// Sends a UDP package over the specified broadcast IP and port and waits for responses.
        /// Some background: http://www.upnp-hacks.org/upnp.html, http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf
        /// Refactored May 2016 Chris Fox, using code/structures from DeviceSpy - see http://www.meshcommander.com/upnptools
        /// </summary>
        ///
        public void Discover()          // this cannot be a static class because it uses async callbacks
        {
            // create the discovery message to broadcast..
            HTTPMessage request  = new HTTPMessage();
            IPEndPoint  RemoteEP = new IPEndPoint(IPAddress.Parse(_broadcastIP), _broadcastPort);

            request.Directive    = "M-SEARCH";
            request.DirectiveObj = "*";
            request.AddTag("ST", _searchTarget);
            request.AddTag("MX", "2");
            request.AddTag("MAN", "\"ssdp:discover\"");
            request.AddTag("HOST", RemoteEP.ToString()); // "239.255.255.250:1900"
            byte[] buffer = UTF8Encoding.UTF8.GetBytes(request.StringPacket);

            // get the local network interfaces... we will braodcast and receive responses on each interface we find...
            ArrayList AddressTable = new ArrayList();
            Hashtable Sessions     = new Hashtable(); // used to keep track of reponses

            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface i in interfaces)
            {
                if (i.IsReceiveOnly == false && i.OperationalStatus == OperationalStatus.Up && i.SupportsMulticast == true)
                {
                    IPInterfaceProperties i2 = i.GetIPProperties();
                    foreach (UnicastIPAddressInformation i3 in i2.UnicastAddresses)
                    {
                        if (!AddressTable.Contains(i3.Address) &&
                            !i3.Address.Equals(IPAddress.IPv6Loopback) &&
                            !i3.Address.Equals(IPAddress.Loopback))
                        {
                            AddressTable.Add(i3.Address);
                        }
                    }
                }
            }
            // AddressTable now contains a list of non-loopback network interfaces that are up
            //Now broadcast via each of them..

            foreach (IPAddress localaddr in AddressTable)
            {
                // set up a listener...
                // Look up in Sessions keyed by local addr - if not found, create and add
                UdpClient cl = (UdpClient)Sessions[localaddr];      // get previusly-used client
                if (cl == null)
                {
                    cl = new UdpClient(new IPEndPoint(localaddr, 0));   // make a new one - bound to local address and random port
                    cl.EnableBroadcast = true;
                    cl.BeginReceive(new AsyncCallback(OnReceive), cl);  // set up an async receive, pass in the UDP Client details
                    Sessions[localaddr] = cl;
                }

                if (RemoteEP.AddressFamily != cl.Client.AddressFamily)
                {
                    continue;
                }
                if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)cl.Client.LocalEndPoint).Address.IsIPv6LinkLocal == true && RemoteEP != OpenSource.UPnP.Utils.UpnpMulticastV6EndPoint2)
                {
                    continue;
                }
                if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)cl.Client.LocalEndPoint).Address.IsIPv6LinkLocal == false && RemoteEP != OpenSource.UPnP.Utils.UpnpMulticastV6EndPoint1)
                {
                    continue;
                }

                IPEndPoint lep = (IPEndPoint)cl.Client.LocalEndPoint;
                if (cl.Client.AddressFamily == AddressFamily.InterNetwork)
                {
                    cl.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, localaddr.GetAddressBytes());
                }
                else if (cl.Client.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    cl.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface, BitConverter.GetBytes((int)localaddr.ScopeId));
                }
                cl.Send(buffer, buffer.Length, RemoteEP);               // and do the broadcast
            }

            // now wait a little while for the replies to come back...

            System.Threading.Thread.Sleep(_timeout);
        }   // Discover
예제 #3
0
        /// <summary>
        /// Parses a Byte Array at a specific location, and builds a Packet.
        /// </summary>
        /// <param name="buffer">The Array of Bytes</param>
        /// <param name="indx">The Start Index</param>
        /// <param name="count">The number of Bytes to process</param>
        /// <returns></returns>
        static public HTTPMessage ParseByteArray(byte[] buffer, int indx, int count)
        {
            HTTPMessage  TheMessage = new HTTPMessage();
            UTF8Encoding UTF8       = new UTF8Encoding();
            String       TempData   = UTF8.GetString(buffer, indx, count);
            DText        parser     = new DText();
            String       TempString;

            int idx = TempData.IndexOf("\r\n\r\n");

            if (idx < 0)
            {
                return(null);
            }
            TempData = TempData.Substring(0, idx);

            parser.ATTRMARK = "\r\n";
            parser.MULTMARK = ":";
            parser[0]       = TempData;
            string CurrentLine = parser[1];

            DText HdrParser = new DText();

            HdrParser.ATTRMARK = " ";
            HdrParser.MULTMARK = "/";
            HdrParser[0]       = CurrentLine;

            if (CurrentLine.ToUpper().StartsWith("HTTP/") == true)
            {
                TheMessage.ResponseCode = int.Parse(HdrParser[2]);
                int s1 = CurrentLine.IndexOf(" ");
                s1 = CurrentLine.IndexOf(" ", s1 + 1);
                TheMessage.ResponseData = HTTPMessage.UnEscapeString(CurrentLine.Substring(s1));
                try
                {
                    TheMessage.Version = HdrParser[1, 2];
                }
                catch (Exception ex)
                {
                    //OpenSource.Utilities.EventLogger.Log(ex);
                    TheMessage.Version = "0.9";
                }
            }
            else
            {
                TheMessage.Directive = HdrParser[1];
                TempString           = CurrentLine.Substring(CurrentLine.LastIndexOf(" ") + 1);
                if (TempString.ToUpper().StartsWith("HTTP/") == false)
                {
                    TheMessage.Version      = "0.9";
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(TempString);
                }
                else
                {
                    TheMessage.Version = TempString.Substring(TempString.IndexOf("/") + 1);
                    int fs = CurrentLine.IndexOf(" ") + 1;
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(CurrentLine.Substring(
                                                                             fs,
                                                                             CurrentLine.Length - fs - TempString.Length - 1));
                }
            }
            String Tag     = "";
            String TagData = "";

            for (int line = 2; line <= parser.DCOUNT(); ++line)
            {
                if (Tag != "" && parser[line, 1].StartsWith(" "))
                {
                    TagData = parser[line, 1].Substring(1);
                }
                else
                {
                    Tag     = parser[line, 1];
                    TagData = "";
                    for (int i = 2; i <= parser.DCOUNT(line); ++i)
                    {
                        if (TagData == "")
                        {
                            TagData = parser[line, i];
                        }
                        else
                        {
                            TagData = TagData + parser.MULTMARK + parser[line, i];
                        }
                    }
                }
                TheMessage.AppendTag(Tag, TagData);
            }
            int cl = 0;

            if (TheMessage.HasTag("Content-Length"))
            {
                try
                {
                    cl = int.Parse(TheMessage.GetTag("Content-Length"));
                }
                catch (Exception ex)
                {
                    //OpenSource.Utilities.EventLogger.Log(ex);
                    cl = -1;
                }
            }
            else
            {
                cl = -1;
            }

            byte[] tbuffer;
            if (cl > 0)
            {
                tbuffer = new byte[cl];
                if ((idx + 4 + cl) > count)
                {
                    // NOP
                }
                else
                {
                    Array.Copy(buffer, idx + 4, tbuffer, 0, cl);
                    TheMessage.DataBuffer = tbuffer;
                }
            }
            if (cl == -1)
            {
                tbuffer = new Byte[count - (idx + 4)];
                Array.Copy(buffer, idx + 4, tbuffer, 0, tbuffer.Length);
                TheMessage.DataBuffer = tbuffer;
            }
            if (cl == 0)
            {
                TheMessage.DataBuffer = new byte[0];
            }
            return(TheMessage);
        }