/// <summary>
        /// starts the mini web server to handle local device requests
        /// if not already running
        /// </summary>
        private void StartLocalDeviceHandler()
        {
            lock (local_device_handler_started_lock)
            {
                if (!local_device_handler_started)
                {
                    local_device_handler_started = true;

                    //local_device_timer = new System.Timers.Timer((max_age - 5) * 1000);
                    local_device_timer = new System.Timers.Timer(local_device_timer_interval * 1000); //check every 5 seconds if an announcement needs to be made
                    local_device_timer.AutoReset = true;
                    local_device_timer.Elapsed += delegate(object sender, ElapsedEventArgs e)
                    {
                        AnnouncementTimerCheck();
                    };
                    local_device_timer.Start();

                    local_device_handler = new MiniWebServer();
                    local_device_handler.SetupListeningSocket();
                    local_device_handler.RequestReceived += delegate(MiniWebServer request_server, MiniWebServer.Request request)
                        {

                            int device_id = -1;
                            string device_id_string = "-1";
                            int device_id_start = request.Url.IndexOf("/device/");
                            if (device_id_start != -1)
                            {
                                device_id_string = request.Url.Substring(device_id_start + "/device/".Length);
                                int device_id_end = device_id_string.IndexOf("/");
                                if (device_id_end != -1)
                                {
                                    device_id_string = device_id_string.Substring(0, device_id_end);
                                    //Console.WriteLine("device id string: " + device_id_string);
                                }
                            }
                            try
                            {
                                device_id = int.Parse(device_id_string);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("error parsing device id: " + ex.Message);
                            }

                            int service_id = -1;
                            string service_id_string = "-1";
                            int service_id_start = request.Url.IndexOf("/service/");
                            if (service_id_start != -1)
                            {
                                service_id_string = request.Url.Substring(service_id_start + "/service/".Length);
                                int service_id_end = service_id_string.IndexOf("/");
                                if (service_id_end != -1)
                                {
                                    service_id_string = service_id_string.Substring(0, service_id_end);
                                    //Console.WriteLine("service id string: " + service_id_string);
                                }
                            }

                            try
                            {
                                service_id = int.Parse(service_id_string);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("error parsing service id: " + ex.Message);
                            }

                            if (device_id != -1)
                            {
                                //if (device_id >= local_devices.Count)
                                //    request.RequestClient.TellNotFound();
                                LocalDevice device = GetLocalDeviceByDeviceID(device_id);
                                if (device == null)
                                {
                                    Console.WriteLine("Device in url (" + device_id + ") not found.");
                                    request.RequestClient.TellNotFound();
                                    return;
                                }

                                if (service_id != -1)
                                {
                                    if (service_id >= device.RootDevice.Services.Count)
                                    {
                                        request.RequestClient.TellNotFound();
                                        return;
                                    }
                                    if (request.Url.EndsWith("/scpd.xml"))
                                    {
                                        //TODO add correct scpd of service in here
                                        //Console.WriteLine("Clients want the service description xml. -> oops ;-)");
                                        SubDevice.Service control_service = device.RootDevice.Services[service_id];
                                        //Console.WriteLine("opened description url of service :" + control_service.ServiceType);
                                        request.RequestClient.Answer(device.Description(request, service_id), "text/xml");
                                    }
                                    else if (request.Url.EndsWith("/control"))
                                    {
                                        request.RequestClient.Answer(device.Control(request, service_id), "text/xml");
                                    }
                                    else if (request.Url.EndsWith("/event"))
                                    {
                                        SubDevice.Service control_service = device.RootDevice.Services[service_id];
                                        //SubDevice.Service control_service = local_devices[device_id].RootDevice.GetServiceByID(service_id);
                                        //Console.WriteLine("opened event url of service :" + control_service.ServiceType);
                                        request.RequestClient.Answer(device.Event(request, service_id), "text/xml");
                                    }
                                }
                                else if (request.Url.EndsWith("/root.xml"))
                                {
                                    string root_description = "";
                                    root_description += "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
                                    root_description += "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">";
                                    root_description += "<specVersion>";
                                    root_description += "<major>" + device.SpecVersionMajor + "</major>";
                                    root_description += "<minor>" + device.SpecVersionMinor + "</minor>";
                                    root_description += "</specVersion>";
                                    root_description += "<device>";
                                    root_description += "<deviceType>urn:" + device.RootDevice.DeviceType + "</deviceType>";
                                    //root_description += "<INMPR03>1.0</INMPR03>";
                                    root_description += "<friendlyName>" + device.RootDevice.FriendlyName + "</friendlyName>";
                                    root_description += "<manufacturer>" + device.RootDevice.Manufacturer + "</manufacturer>";
                                    root_description += "<manufacturerURL>" + device.RootDevice.ManufacturerUrl + "</manufacturerURL>";
                                    root_description += "<modelDescription>" + device.RootDevice.ModelDescription + "</modelDescription>";
                                    root_description += "<modelName>" + device.RootDevice.ModelName + "</modelName>";
                                    root_description += "<modelNumber>" + device.RootDevice.ModelNumber + "</modelNumber>";
                                    root_description += "<modelURL>" + device.RootDevice.ModelUrl + "</modelURL>";
                                    root_description += "<UDN>uuid:" + device.RootDevice.UniversalUniqueID + "</UDN>";
                                    root_description += "<serviceList>";
                                    int service_index = 0;
                                    foreach (SubDevice.Service service in device.RootDevice.Services)
                                    {
                                        root_description += "<service>";
                                        root_description += "<serviceType>urn:" + service.ServiceType + "</serviceType>";
                                        root_description += "<serviceId>urn:" + service.ServiceID + "</serviceId>";
                                        root_description += "<SCPDURL>/device/" + device.DeviceID + "/service/" + service_index + "/scpd.xml</SCPDURL>";
                                        root_description += "<controlURL>/device/" + device.DeviceID + "/service/" + service_index + "/control</controlURL>";
                                        root_description += "<eventSubURL>/device/" + device.DeviceID + "/service/" + service_index + "/event</eventSubURL>";
                                        root_description += "</service>";
                                        service_index++;
                                    }
                                    root_description += "</serviceList>";
                                    root_description += "</device>";
                                    root_description += "</root>";
                                    request.RequestClient.Answer(root_description, "text/xml");
                                }
                                else request.RequestClient.TellNotFound();

                            }
                            else request.RequestClient.TellNotFound();
                        };
                }
            }
        }
        public void TestMediaRendererSetPlaybackUrlWithMiniWebServer()
        {
            Console.WriteLine("Test to set a playback url of a media renderer with a mini web server.");
            UPnP u = new UPnP();
            u.SetupSockets();
            MiniWebServer server = new MiniWebServer();
            server.Port = 80;
            server.SetupListeningSocket();

            bool wait = true;
            server.RequestReceived += delegate(MiniWebServer request_server, MiniWebServer.Request request)
            {
                Console.WriteLine("Request received: ");
                Console.WriteLine("URL: " + request.Url);
                Console.WriteLine("Method: " + request.Method);
                Console.WriteLine("Version: " + request.Version);
                Console.WriteLine("Headers:");
                foreach (string key in request.Headers.Keys)
                {
                    Console.WriteLine("[" + key + "]" + ":[" + request.Headers.Get(key) + "]");
                }
                if (request.Url == "/")
                {
                    string page = "";
                    //string type = "text/plain";
                    page = "<html>\n<head>\n<title>MiniWebServer Test Page</title>\n</head>\n<body bgcolor=\"#333355\">Test Page of the Miniwebserver running on port: " + server.Port + "<br><a href=\"/test.mp3\">Test Mp3</a></body>\n</html>\n";
                    string type = "text/html";
                    request.RequestClient.Answer(page, type);
                }
                else if (request.Url == "/test.mp3")
                {
                    byte[] mp3 = File.ReadAllBytes("..\\..\\..\\TestDateien\\test.mp3");
                    string type = "audio/mpeg";
                    request.RequestClient.Answer(mp3, type);
                }
            };

            u.DeviceDiscovered += delegate(Device d)
            {
                if (d.DeviceType == Device.DeviceTypes.MediaRenderer)
                {
                    MediaRenderer mr = (MediaRenderer)d;
                    mr.SettingPlaybackUrlCompleted += delegate(MediaRenderer sp, bool was_successful)
                    {
                        if (was_successful)
                            Console.WriteLine("Set a playback url.");
                        //wait = !was_successful;
                    };
                    mr.PressingButtonCompleted += delegate(MediaRenderer sp, MediaRenderer.Button pressed, bool was_successful)
                    {
                        if (was_successful)
                            Console.WriteLine("Pressed the " + Enum.GetName(typeof(MediaRenderer.Button), pressed) + " button.");
                        wait = !was_successful;
                    };

                    mr.InformationGathered += delegate(Device dimr, bool was_successful)
                    {
                        MediaRenderer mir = (MediaRenderer)dimr;
                        if (was_successful)
                        {
                            Console.WriteLine("");
                            Console.WriteLine("-- Gathered media renderer information --");
                            Console.WriteLine("SpecVersion: " + mir.SpecVersionMajor + "." + mir.SpecVersionMinor);
                            Console.WriteLine("URLBase: " + mir.UrlBase);
                            if (mir.RootDevice != null)
                            {
                                Console.WriteLine("presentationURL: " + mir.RootDevice.PresentationUrl);
                                Console.WriteLine("friendlyName: " + mir.RootDevice.FriendlyName);
                                Console.WriteLine("manufacturer: " + mir.RootDevice.Manufacturer);
                                Console.WriteLine("manufacturerURL: " + mir.RootDevice.ManufacturerUrl);
                                Console.WriteLine("modelDescription: " + mir.RootDevice.ModelDescription);
                                Console.WriteLine("modelName: " + mir.RootDevice.ModelName);
                                Console.WriteLine("Number of Sub Devices: " + mir.RootDevice.Devices.Count);
                                Console.WriteLine("Sub UUID: " + mir.RootDevice.UniversalUniqueID);
                                //Thread.Sleep(3000);
                                mir.SetPlaybackUrl("http://" + ip + "/test.mp3");
                                Thread.Sleep(1000);
                                mir.Press(MediaRenderer.Button.Play);
                            }
                            //Console.WriteLine("Server: " + r.Server);
                            Console.WriteLine("UUID: " + mir.UniversalUniqueID);
                            Console.WriteLine("-- Gathered media renderer information --");
                            Console.WriteLine("");
                        }
                        else Console.WriteLine("failed to gather media renderer information");
                    };
                    mr.GatherInformation();//TODO this could also be done by upnp after it fired the discovered event

                    Console.WriteLine("");
                    Console.WriteLine("-- Discovered a media renderer --");
                    Console.WriteLine("Server: " + mr.Server);
                    Console.WriteLine("Host: " + mr.Host + ":" + mr.Port);
                    Console.WriteLine("UUID: " + mr.UniversalUniqueID);
                    Console.WriteLine("Location: " + mr.Location);
                    Console.WriteLine("Unique Service Name: " + mr.UniqueServiceName);
                    Console.WriteLine("-- Discovered a media renderer --");
                    Console.WriteLine("");
                    //Assert.IsTrue(!string.IsNullOrEmpty(ex_ip_completed.MyIP), "no ip address fetched");
                }
            };
            u.StartDiscovery();
            Console.WriteLine("Waiting for data");
            DateTime start = DateTime.Now;
            while (wait)
            {
                if (DateTime.Now - start > new TimeSpan(0, 0, 300))
                {
                    Console.WriteLine("");
                    Console.WriteLine("Operation took too long");
                    wait = false;
                    Assert.Fail("Operation took too long");
                }
                Console.Write(".");
                Thread.Sleep(250);
            }
            Console.WriteLine("UPnP Media Renderer Set Playback URL With Mini Web Server Test successful.");

            u.CloseSockets();
        }
 public void TestMiniWebServerOpenClose()
 {
     Console.WriteLine("Test to Open/Close the Mini Web Server.");
     MiniWebServer server = new MiniWebServer();
     server.SetupListeningSocket();
     server.CloseListeningSocket();
     Console.WriteLine("Mini Web Server Open/Close Test successful.");
 }
        public void TestMiniWebServerRequest()
        {
            Console.WriteLine("Test to see if requesting works.");
            MiniWebServer server = new MiniWebServer();
            server.Port = 80;
            server.SetupListeningSocket();

            bool wait = true;
            server.RequestReceived += delegate(MiniWebServer request_server, MiniWebServer.Request request)
            {
                Console.WriteLine("Request received: ");
                Console.WriteLine("URL: " + request.Url);
                Console.WriteLine("Method: " + request.Method);
                Console.WriteLine("Version: " + request.Version);
                Console.WriteLine("Headers:");
                foreach (string key in request.Headers.Keys)
                {
                    Console.WriteLine("[" + key + "]" + ":[" + request.Headers.Get(key) + "]");
                }
                //request.RequestClient.TellNotFound();

                //request.RequestClient.Answer("HTTP/1.0 302 Moved Temporarily\r\nSERVER: MiniWebServer\r\nLOCATION: http://192.168.0.1:80/Public_UPNP_gatedesc.xml\r\n\r\n");
                if (request.Url == "/")
                {
                    string page = "";
                    //string type = "text/plain";
                    page = "<html>\n<head>\n<title>MiniWebServer Test Page</title>\n</head>\n<body bgcolor=\"#333355\">Test Page of the Miniwebserver running on port: " + server.Port + "<br><a href=\"/test.mp3\">Test Mp3</a></body>\n</html>\n";
                    string type = "text/html";
                    request.RequestClient.Answer(page, type);
                }
                else if (request.Url == "/test.mp3")
                {
                    byte[] mp3 = File.ReadAllBytes("..\\..\\..\\TestDateien\\test.mp3");
                    string type = "audio/mpeg";
                    request.RequestClient.Answer(mp3, type);
                }

                    //request.RequestClient.Answer("HTTP/1.1 200 OK\r\nSERVER: MiniWebServer\r\nContent-Type: text/plain\r\nContent-Length: " + page.Length + "\r\nConnection: Close\r\n\r\n" + page);

                //Thread.Sleep(300);
                //request.RequestClient.Disconnect();
                //Assert.IsTrue(!string.IsNullOrEmpty(ex_ip_completed.MyIP), "no ip address fetched");
                //wait = false;
            };
            Console.WriteLine("Waiting for data");
            DateTime start = DateTime.Now;
            while (wait)
            {
                if (DateTime.Now - start > new TimeSpan(0, 0,120))
                {
                    Console.WriteLine("");
                    Console.WriteLine("Operation took too long");
                    Assert.Fail("Operation took too long");
                    wait = false;
                }
                Console.Write(".");
                Thread.Sleep(250);
            }
            Console.WriteLine("");
            server.CloseListeningSocket();
            Console.WriteLine("Mini Web Server Request Test successful.");
        }
        public void TestMiniWebServerAutoFileAnswerRequest()
        {
            Console.WriteLine("Test to see if requesting using the file answer method works.");
            MiniWebServer server = new MiniWebServer();
            server.Port = 80;
            server.SetupListeningSocket();
            long page_len = 0;
            long ret_page_len = 1; //to make sure no false positive could occur
            bool wait = true;
            server.RequestReceived += delegate(MiniWebServer request_server, MiniWebServer.Request request)
            {
                Console.WriteLine("Request received: ");
                Console.WriteLine("URL: " + request.Url);
                Console.WriteLine("Method: " + request.Method);
                Console.WriteLine("Version: " + request.Version);
                Console.WriteLine("Headers:");
                foreach (string key in request.Headers.Keys)
                {
                    Console.WriteLine("[" + key + "]" + ":[" + request.Headers.Get(key) + "]");
                }
                //request.RequestClient.TellNotFound();

                //request.RequestClient.Answer("HTTP/1.0 302 Moved Temporarily\r\nSERVER: MiniWebServer\r\nLOCATION: http://192.168.0.1:80/Public_UPNP_gatedesc.xml\r\n\r\n");
                if (request.Url == "/")
                {
                    string page = "";
                    //string type = "text/plain";
                    page = "<html>\n<head>\n<title>MiniWebServer Test Page</title>\n</head>\n<body bgcolor=\"#333355\">Test Page of the Miniwebserver running on port: " + server.Port + "<br><a href=\"/test.mp3\">Test Mp3</a></body>\n</html>\n";
                    string type = "text/html";
                    page_len = page.Length;
                    request.RequestClient.Answer(page, type);
                }
                else if (request.Url == "/test.mp3")
                {
                    FileInfo fi = new FileInfo("..\\..\\..\\TestDateien\\test.mp3");
                    page_len = fi.Length;
                    request.RequestClient.FileAnswer("..\\..\\..\\TestDateien\\test.mp3");
                }

                //request.RequestClient.Answer("HTTP/1.1 200 OK\r\nSERVER: MiniWebServer\r\nContent-Type: text/plain\r\nContent-Length: " + page.Length + "\r\nConnection: Close\r\n\r\n" + page);

                //Thread.Sleep(300);
                //request.RequestClient.Disconnect();
                //Assert.IsTrue(!string.IsNullOrEmpty(ex_ip_completed.MyIP), "no ip address fetched");
                //wait = false;
            };

            WebClient wc = new WebClient();
            wc.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
            {
                if (!e.Cancelled && e.Result != null)
                {
                    for (int i = 0; i < wc.ResponseHeaders.Count; i++)
                    {
                        Console.WriteLine("Header[" + i + "]: " + wc.ResponseHeaders.GetKey(i)+" : "+wc.ResponseHeaders[i]);
                    }
                    //Console.WriteLine("Content-Type: " + wc.Headers.Get("Content-Type"));
                    ret_page_len = e.Result.Length;
                    wait = false;
                }
            };
            wc.DownloadDataAsync(new Uri("http://127.0.0.1/test.mp3"));

            Console.WriteLine("Waiting for data");
            DateTime start = DateTime.Now;
            while (wait)
            {
                if (DateTime.Now - start > new TimeSpan(0, 0, 120))
                {
                    Console.WriteLine("");
                    Console.WriteLine("Operation took too long");
                    Assert.Fail("Operation took too long");
                    wait = false;
                }
                Console.Write(".");
                Thread.Sleep(250);
            }
            Assert.IsTrue(page_len == ret_page_len, "Test failed: received an incomplete page");
            Console.WriteLine("");
            server.CloseListeningSocket();
            wc.Dispose();
            Console.WriteLine("Mini Web Server Request using File Answer Method Test successful.");
        }