internal void Parse(Connection connection, string message)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccListener::Parse()");
            Match  match     = parser.Match(message);
            string requestor = match.Groups[1].ToString();

            string[] tokens = tokenizer.Split(match.Groups[2].ToString().Trim());
            switch (tokens[Action])
            {
            case CHAT:
                if (OnDccChatRequest != null)
                {
                    //Test for sufficient number of arguments
                    if (tokens.Length < 4)
                    {
                        connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect CHAT arguments: " + message);
                        return;
                    }
                    //Send event
                    DccUserInfo dccUserInfo = null;
                    try
                    {
                        dccUserInfo = new DccUserInfo(
                            connection,
                            Rfc2812Util.ParseUserInfoLine(requestor),
                            new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture)));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.BadDccEndpoint, "Invalid TCP/IP connection information sent.");
                        return;
                    }
                    try
                    {
                        OnDccChatRequest(dccUserInfo);
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case SEND:
                //Test for sufficient number of arguments
                if (tokens.Length < 5)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect SEND arguments: " + message);
                    return;
                }
                if (OnDccSendRequest != null)
                {
                    DccUserInfo dccUserInfo = null;
                    try
                    {
                        dccUserInfo = new DccUserInfo(
                            connection,
                            Rfc2812Util.ParseUserInfoLine(requestor),
                            new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture)));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.BadDccEndpoint, ae.ToString());
                        return;
                    }
                    try
                    {
                        OnDccSendRequest(
                            dccUserInfo,
                            tokens[FileName],
                            int.Parse(tokens[FileSize], CultureInfo.InvariantCulture),
                            IsTurbo(5, tokens));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case GET:
                //Test for sufficient number of arguments
                if (tokens.Length < 2)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect GET arguments: " + message);
                    return;
                }
                if (OnDccGetRequest != null)
                {
                    try
                    {
                        OnDccGetRequest(
                            new DccUserInfo(
                                connection,
                                Rfc2812Util.ParseUserInfoLine(requestor)),
                            tokens[FileName],
                            IsTurbo(2, tokens));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case ACCEPT:
                //Test for sufficient number of arguments
                if (tokens.Length < 4)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC ACCEPT arguments: " + message);
                    return;
                }
                //DccListener will try to handle Receive at correct file position
                try
                {
                    DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("C" + tokens[2]);
                    session.OnDccAcceptReceived(long.Parse(tokens[3], CultureInfo.InvariantCulture));
                }
                catch (ArgumentException e)
                {
                    connection.Listener.Error(ReplyCode.UnableToResume, e.ToString());
                }
                break;

            case RESUME:
                //Test for sufficient number of arguments
                if (tokens.Length < 4)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC RESUME arguments: " + message);
                    return;
                }
                //DccListener will automatically handle Resume/Accept interaction
                try
                {
                    DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("S" + tokens[2]);
                    session.OnDccResumeRequest(long.Parse(tokens[3], CultureInfo.InvariantCulture));
                }
                catch (ArgumentException e)
                {
                    connection.Listener.Error(ReplyCode.UnableToResume, e.ToString());
                }
                break;

            default:
                connection.Listener.Error(ReplyCode.UnparseableMessage, message);
                Debug.WriteLineIf(DccUtil.DccTrace.TraceError, "[" + Thread.CurrentThread.Name + "] DccListener::Parse() Unknown DCC command");
                break;
            }
        }