/// <summary>
        /// Runs server thread.
        /// Perform server polling for new requests.
        /// </summary>
        private void Run()
        {
            Debug.WriteLine("Starting Server Thread with ID: " + serverIndex + " at " + DateTime.Now.ToString());
            Http http = new Http(serverIndex);

            while (settings.Servers[serverIndex].Cookie == null)
            {
                Thread.Sleep(1000);
            }

            while (true)
            {
                bool receiveNow = false;
                lock (thisLock)
                {
                    receiveNow = (queues.Values.Count > 0);
                }
                // nothing to do - wait
                if (!receiveNow)
                {
                    Thread.Sleep(http.fetchMessageTimeoutRetryDelay);
                    continue;
                }
                else
                {
                    // TODO: Handle situation when network is down
                    Debug.WriteLine("Entering FetchMessage at " + DateTime.Now.ToString());
                    ServerResponse sr = http.FetchMessage(settings.Servers[serverIndex].InstanceId, settings.Servers[serverIndex].Cookie, settings.Servers[serverIndex].LastMessageId);
                    // check if message is valid
                    if (sr.token == null)
                    {
                        Debug.WriteLine("Skipped message with empty token");
                        continue;
                    }
                    OutgoingMessage om = new OutgoingMessage {
                        Action = "Received", Id = sr.id, Token = sr.token, Data = JsonConvert.SerializeObject(sr.data)
                    };
                    Debug.WriteLine("Entering send message at " + DateTime.Now.ToString());
                    int    currentReaders = 0;
                    string path;
                    string args;
                    lock (thisLock)
                    {
                        try
                        {
                            AppInfo ai = settings.Servers[serverIndex].Queues.First(queue => queue.Token.Equals(om.Token));
                            if (queues.ContainsKey(ai.GetKey()))
                            {
                                P2PMessageQueue q = queues[ai.GetKey()];
                                currentReaders = q.CurrentReaders;
                                path           = ai.Path;
                                args           = ai.Args;
                            }
                            else
                            {
                                Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                                continue;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                            continue;
                        }
                    }

                    // if no readers - start the app and make sure that Ai is still valid
                    bool messageSkipped = false;
                    if (currentReaders == 0)
                    {
                        Process.Start(path, args);
                        while (currentReaders == 0)
                        {
                            Thread.Sleep(10000);
                            lock (thisLock) {
                                try
                                {
                                    AppInfo ai = settings.Servers[serverIndex].Queues.First(queue => queue.Token.Equals(om.Token));
                                    if (queues.ContainsKey(ai.GetKey()))
                                    {
                                        P2PMessageQueue q = queues[ai.GetKey()];
                                        currentReaders = q.CurrentReaders;
                                    }
                                    else
                                    {
                                        Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                                        messageSkipped = true;
                                        break;
                                    }
                                }
                                catch (InvalidOperationException)
                                {
                                    Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                                    messageSkipped = true;
                                    break;
                                }
                            }
                        }
                        if (messageSkipped)
                        {
                            continue;
                        }
                        // give a chance for the client app to fully initialize
                        Thread.Sleep(10000);
                    }

                    // send the message
                    lock (thisLock)
                    {
                        try
                        {
                            AppInfo ai = settings.Servers[serverIndex].Queues.First(queue => queue.Token.Equals(om.Token));
                            if (queues.ContainsKey(ai.GetKey()))
                            {
                                P2PMessageQueue q = queues[ai.GetKey()];

                                string  data    = JsonConvert.SerializeObject(om);
                                Message message = new Message(Encoding.UTF8.GetBytes(data), false);
                                Debug.WriteLine("About to send message at " + DateTime.Now.ToString());
                                ReadWriteResult result = q.Send(message, 0);

                                // If message delivered save its id
                                // TODO: Verify client responce to ensure message is readed
                                if (result == ReadWriteResult.OK)
                                {
                                    settings.Servers[serverIndex].LastMessageId = sr.id;
                                    Settings.Save(settings);
                                }
                                else
                                {
                                    Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token + ", result of Send is : " + result.ToString());
                                }

                                Debug.WriteLine("Delivered: " + ai.GetKey() + ", " + data + " at " + DateTime.Now.ToString());
                            }
                            else
                            {
                                Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            Debug.WriteLine("Skipped: " + om.Id + ", " + om.Token);
                        }
                    }
                }
            }
        }