/// <summary>
        /// Interpret a single command 
        /// </summary>
        /// <param name="received_command">the command to interpret</param>
        private void InterpretCommand(string received_command)
        {
            int command_end = received_command.IndexOf(" ");
            if (command_end == -1) command_end = received_command.Length;

            if (command_end != -1)
            {
                string parameter = "";
                string[] parameters ={ };
                string command = received_command.Substring(1);
                if (command_end != received_command.Length)
                {
                    command = received_command.Substring(1, command_end - 1);
                    parameter = received_command.Substring(command_end + 1);
                    parameters = parameter.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    //Console.WriteLine("Command: '" + command + "' ,Parameter(" + parameters.Length + "): '" + parameter + "'");
                }
                switch (command)
                {
                    case "HubName" :
                        //Console.WriteLine("Hubname Command received: " + parameter);
                        name = parameter;
                        //fire nameChange event
                        break;

                    case "Hello" :
                        //Console.WriteLine("Hello Command received: " + parameters[0]);
                        if (!is_logged_in)
                        {
                            is_logged_in = true;
                            SendCommand("Version", my_version);
                            SendCommand("GetNickList");
                            SendMyInfo();
                            //Console.WriteLine("Logged in Hub: "+name);
                            try
                            {
                                if (LoggedIn != null)
                                    LoggedIn(this);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("Exception in LoggedIn: " + ex.Message);
                            }
                        }
                        else
                        {//new user announced by server
                            //Console.WriteLine("User "+parameters[0]+" has joined Hub: "+name);
                            UserListAdd(parameters[0]);
                        }
                        break;

                    case "Quit":
                        //Console.WriteLine("User "+parameters[0]+" has left Hub: "+name);
                        UserListRemove(parameters[0]);
                        break;

                    case "NickList":
                        Console.WriteLine("NickList Message received.");
                        UserListClear();
                        string[] temp_users = parameters[0].Split("$$".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        foreach (string temp_user in temp_users)
                        {
                            UserListAdd(temp_user);
                        }
                        break;

                    case "OpList":
                        op_list.Clear();
                        string[] temp_ops = parameters[0].Split("$$".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        foreach (string temp_op in temp_ops)
                        {
                            op_list.Add(temp_op);
                        }
                        break;

                    case "ConnectToMe":
                            try
                            {
                                string peer_address = "";
                                if (parameters.Length == 2)
                                {
                                    peer_address = parameters[1];
                                }
                                else if (parameters.Length == 3)
                                {
                                    peer_address = parameters[2];
                                }
                                else break;
                                Peer peer = new Peer(peer_address); //add username also, to counter possible network attacks
                                if (ConnectToMeReceived != null)
                                    ConnectToMeReceived(this, peer);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("Exception in ConnectToMe EventHandler: " + ex.Message);
                            }
                        break;

                    case "RevConnectToMe":
                        SendConnectToMe(parameters[0]);
                        break;

                    case "HubTopic":
                        //topic = parameters[0];
                        topic = parameter;
                        break;

                    case "UserCommand":
                        //Console.WriteLine("User Command received: "+parameter);
                        //TODO support user context menu entries
                        break;

                    case "Search":
                        //Console.WriteLine("Search Command received: "+parameter);
                        SearchParameters search = new SearchParameters();
                        if(parameters[0].StartsWith("Hub:"))
                        {
                            search.mode = ConnectionMode.Passive;
                            int username_start = parameters[0].IndexOf(":");
                            if (username_start == -1 || username_start + 1 > parameters[0].Length) break;
                            search.username = parameters[0].Substring(username_start + 1);
                        }
                        else
                        {
                            search.mode = ConnectionMode.Active;
                            int port_start = parameters[0].IndexOf(":");
                            if (port_start == -1 || port_start + 1 > parameters[0].Length) break;
                            search.ip = parameters[0].Substring(0,port_start);
                            try
                            {
                                search.port = int.Parse(parameters[0].Substring(port_start + 1));
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("error parsing port in search: " + ex.Message);
                                break;
                            }
                        }

                        char[] seps ={ '?' };
                        string[] search_parameters = parameters[1].Split(seps,StringSplitOptions.RemoveEmptyEntries);
                        if (search_parameters.Length < 4) break;
                        if (search_parameters[0] == "F")
                            search.size_restricted = false;
                        else search.size_restricted = true;
                        if (search_parameters[1] == "F")
                            search.is_max_size = false;
                        else search.is_max_size = true;
                        try
                        {
                            search.size = long.Parse(search_parameters[2]);
                            search.file_type = (SearchFileType)int.Parse(search_parameters[3]);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("error parsing ints in search: " + ex.Message);
                            break;
                        }
                        if (search_parameters[4].StartsWith("TTH:") && search.file_type == SearchFileType.tth && search_parameters[4].Length > 4)
                            search.tth = search_parameters[4].Substring(4);
                        else search.search_string = search_parameters[4];
                        //TODO above throws exceptions
                        if (SearchReceived != null)
                            SearchReceived(this,search);
                        break;

                    case "Supports":
                        supports = (string[])parameters.Clone();
                        break;

                    case "UserIP":
                        Console.WriteLine("UserIP Message received: " + parameter);
                        break;

                    case "MCTo:":
                        string mcto_username = parameters[1].Substring(1); //to skip the leading $
                        int mcto_message_start = parameters[0].Length + parameters[1].Length + 2;
                        if (mcto_message_start < parameter.Length)
                        {
                            string mcto_message = parameter.Substring(mcto_message_start);
                            AddChatToHistory(mcto_username, mcto_message);
                        }
                        break;

                    case "To:":
                        //Console.WriteLine("Private Message received: " + parameter);
                        string to_username = parameters[2];
                        int to_message_start = parameters[0].Length + parameters[1].Length + parameters[2].Length + parameters[3].Length + 4;
                        if (to_message_start < parameter.Length )
                        {
                            string to_message = parameter.Substring(to_message_start);
                            ChatLine to_message_line = new ChatLine(to_username, to_message);
                            if (PrivateChatLineReceived != null)
                                PrivateChatLineReceived(this, to_message_line);
                        }
                        break;

                    case "SR":
                        //Console.WriteLine("Search result received: " + parameter);
                        SearchResults.SearchResult result = new SearchResults.SearchResult();
                        result.ResultLine = parameter;
                        try
                        {
                            if (SearchResultReceived != null)
                                SearchResultReceived(this, result);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Exception in event handler: " + ex.Message);
                        }

                        break;

                    case "LogedIn":
                        Console.WriteLine("LogedIn Message received: " + parameter);
                        //what the hell is this and who forgot to take some english lessons ?
                        break;
                    case "MyINFO":
                        //Console.WriteLine("MyINFO Message received: " + parameter);
                        UserListAdd(parameters[1]);
                        break;
                    case "GetPass":
                        Console.WriteLine("GetPass Message received: " + parameter);
                        if (PasswordRequested != null)
                        {
                            string password = PasswordRequested(this);
                            SendPassword(password);
                        }
                        break;

                    case "ForceMove":
                        //Console.WriteLine("FORCE MOVE NOT IMPLEMENTED");
                        if (MoveForced != null)
                        {
                            Hub dst_hub = this.Copy();
                            MoveForced(this, dst_hub);
                        }
                        break;

                    case "ValidateDenide":
                        Console.WriteLine("Nick: "+parameters[0]+" on Hub: " + name + " is already in use.");
                        break;

                    case "HubIsFull":
                        Console.WriteLine("Hub: " + name + " is full.");
                        Disconnect();
                        break;

                    case "Lock" :
                        //Console.WriteLine("Lock Command received: "+parameter);
                        //int key_end = parameter.IndexOf(" ");
                        //if (key_end != -1)
                        //{
                            //string key = parameter.Substring(0, key_end);
                        if (parameters.Length > 1)
                        {
                            string key = parameters[0];
                            //Console.WriteLine("Key: " + key);
                            if (key.StartsWith("EXTENDEDPROTOCOL"))
                            {
                                is_extended_protocol = true;
                                //Console.WriteLine("Hub is using the dc++ protocol enhancements.");
                                //SendCommand("Supports", "UserCommand NoGetINFO NoHello UserIP2 TTHSearch ZPipe0 GetZBlock ");
                                SendCommand("Supports", "UserCommand TTHSearch NoGetINFO NoHello ");
                            }

                            //string decoded_key = MyLockToKey(key);
                            string decoded_key = L2K(key);
                            //Console.WriteLine("Decoded key: " + decoded_key);
                            SendCommand("Key" , decoded_key);
                            SendCommand("ValidateNick", nick);

                        }
                        break;
                    default:
                        Console.WriteLine("Unknown Command received: " + command + ", Parameter: " + parameter);
                        break;
                }
            }
            else Console.WriteLine("Error interpreting command: " + received_command);
        }
        /// <summary>
        /// Setup the event handlers for a fresh connected peer
        /// </summary>
        /// <param name="client">an ungrabbed peer</param>
        private void SetupPeerEventHandler(Peer client)
        {
            client.Nick = nick;
            client.DataReceived += delegate(Peer data_received_client)
            {/*
                    Queue.QueueEntry entry = download_queue.FindFirstUnusedQueueEntryBySourceUser(data_received_client.PeerNick);
                    if (entry != null)
                    {
                        Queue.QueueEntry.Source source = entry.FindFirstSourceByUser(data_received_client.PeerNick);
                        if (source != null)
                        {
                            entry.IsInUse = true;
                        }
                        else
                        {
                            Console.WriteLine("no correct source found in queue entry for user: "******"nothing found in queue for user: "******"files.xml.bz2")
                    file_list_request_client.UploadFilename = file_list_request_client.UploadRequestFilename;
                file_list_request_client.UploadFileListData = shares.GetFileListXmlBZ2();
                return (Peer.FileRequestAnswer.LetsGo);
            };

            client.FileRequestReceived += delegate(Peer file_request_client)
            {
                Sharing.SharingEntry entry = shares.GetShareByFileRequest(file_request_client.UploadRequestFilename);
                if(entry!=null)
                {
                   file_request_client.UploadFilename = entry.Filename;
                   return (Peer.FileRequestAnswer.LetsGo);
                }
                else return (Peer.FileRequestAnswer.FileNotAvailable);
            };

            client.HandShakeCompleted += delegate(Peer handshake_client)
            {
                if (PeerHandShakeCompleted != null)
                    PeerHandShakeCompleted(handshake_client);
                Queue.QueueEntry entry = download_queue.FindFirstUnusedQueueEntryBySourceUser(handshake_client.PeerNick);
                if (entry != null)
                {
                    Queue.QueueEntry.Source source = entry.FindFirstSourceByUser(handshake_client.PeerNick);
                    if (source != null)
                    {
                        //handshake_client.StartDownload(source.Filename, entry.OutputFilename, entry.Filesize);
                        if (entry.Type == Queue.QueueEntry.EntryType.File && entry.WantTTHL)
                            handshake_client.GetTTHL(entry);
                        else if (entry.Type == Queue.QueueEntry.EntryType.File )
                            handshake_client.StartDownload(source, entry);
                        else if (entry.Type == Queue.QueueEntry.EntryType.FileList)
                            handshake_client.GetFileList(entry);
                    }
                    else
                    {
                        Console.WriteLine("no correct source found in queue entry for user: "******"nothing found in queue for user: " + handshake_client.PeerNick);
                        handshake_client.Disconnect();
                    }
                }
            };

            client.Completed += delegate(Peer completed_client)
            {
                //download_queue.Remove(download_queue.FindQueueEntryByOutputFilename(completed_client.OutputFilename));
                if(auto_remove_downloads)
                    download_queue.Remove(completed_client.QueueEntry);
                ContinueWithQueueForUser(completed_client.PeerNick);
                if (PeerCompleted != null)
                    PeerCompleted(completed_client);
            };

            client.Disconnected += delegate(Peer disconnected_client)
            {
                lock (peers_lock)
                {
                    if(peers.Contains(disconnected_client))
                        peers.Remove(disconnected_client);
                }
                //Queue.QueueEntry entry = download_queue.FindQueueEntryByOutputFilename(disconnected_client.OutputFilename);
                //Queue.QueueEntry entry = disconnected_client.QueueEntry;
                //if (entry != null) //TODO this will cause trouble -> fix with disconnect cause change in callback
                //    entry.IsInUse = false;
                //ContinueWithQueueForUser(disconnected_client.PeerNick);//TODO prevent hammering on strange source with a seconds counter
                if (PeerDisconnected != null)
                    PeerDisconnected(disconnected_client);
            };
        }
        /// <summary>
        /// Callback to accept tcp connections
        /// </summary>
        /// <param name="result">Async Result/State</param>
        private void OnAccept(IAsyncResult result)
        {
            if (!IsListening) return;
            if (tcp_socket != null)
            {
                //if(
                if (!tcp_socket.IsBound) return;
                if (!result.IsCompleted) return;
                try
                {

                    if (tcp_socket != ((Socket)result.AsyncState)) return;
                    Socket accept_socket = (Socket)result.AsyncState;
                    if (accept_socket == null) return;
                    if (!accept_socket.IsBound) return;
                    //if (!accept_socket.Connected) return;
                    //Console.WriteLine("trying end accept.");
                    //accept_socket.a
                    Socket client = tcp_socket.EndAccept(result);
                    if (!client.Connected) return;
                    //Console.WriteLine("new client connected.");
                    Peer new_peer = new Peer(client);
                    if (PeerConnected != null)
                    {
                        PeerConnected(new_peer);
                    }

                    //accept_socket.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error accepting connection: " + ex.Message);
                }
                try
                {
                    AsyncCallback event_accept = new AsyncCallback(OnAccept);
                    tcp_socket.BeginAccept(event_accept, tcp_socket);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Fatal Error accepting connection: " + ex.Message);
                }

            }
            else Console.WriteLine("Accept on tcp socket aborted.");
        }