protected virtual void HandleUsr(DispatchConnection c, Command cmd)
        {
            // there are two steps:
            // >>> USR trID SP I userHandle
            // <<< USR trID SP S challenge
            // >>> USR trID SP S response
            // <<< USR trID OK userHandle friendlyName

            // for now, only MD5 is supported
            if (cmd.Params[0] != "MD5")
            {
                Command response = new Command(Error.NotExpected, cmd.TrId);
                Server.Send(c, response);
            }
            else
            {
                if (cmd.Params[1] == "I")
                {
                    HandleUsrI(c, cmd);
                }
                else if (cmd.Params[1] == "S")
                {
                    HandleUsrS(c, cmd);
                }
            }
        }
        public override void HandleCommand(DispatchConnection c, Command cmd)
        {
            switch (cmd.Verb)
            {
            case Verb.Cvr:
                HandleCvr(c, cmd);
                break;

            case Verb.Cvq:
                HandleCvq(c, cmd);
                break;

            case Verb.Inf:
                HandleInf(c, cmd);
                break;

            case Verb.Usr:
                HandleUsr(c, cmd);
                break;

            default:
                HandleUnrecognised(c, cmd);
                break;
            }
        }
        private void HandleUsrI(DispatchConnection c, Command cmd)
        {
            String userHandle = cmd.Params[2];
            String challenge  = AuthenticationService.CreateChallengeString();

            Command response = new Command(Verb.Usr, cmd.TrId, "MD5", "S", challenge);

            Server.Send(c, response);

            c.AuthDetails = new Md5AuthDetails(userHandle, challenge);
        }
        private void HandleUsrS(DispatchConnection c, Command cmd)
        {
            Md5AuthDetails auth       = c.AuthDetails as Md5AuthDetails;
            String         chResponse = cmd.Params[2];

            if (auth == null)
            {
                // ordinarily that would be an Exception condition
                Command response = new Command(Error.AuthenticationFailed, cmd.TrId);
                Server.Send(c, response);
            }
            else
            {
                User user;
                if (AuthenticationService.AuthenticateMd5(auth.UserHandle, auth.Challenge, chResponse, out user) == AuthenticationResult.Success)
                {
                    Command responseOk = new Command(Verb.Usr, cmd.TrId, "OK", user.UserHandle, user.FriendlyName);
                    Server.Send(c, responseOk);

                    /////////////////////////////
                    // Send XFR, otherwise client will use this Dispatch server as a notification server (it starts by sending SYN)
                    // note that the official client deviates from the IETF draft by requiring an additional "0" parameter on the XFR command

                    // curiously, it seems MSN Messenger 1.x caches the last Notification server and reconnects to it directly
                    // in which case you don't send an XFR and instead begin the rest of an NS server's duties

                    String sendTo = NotificationServer.Instance.GetEndPointForClient(c.Socket.LocalEndPoint).ToString();

                    Command responseXfr = new Command(Verb.Xfr, cmd.TrId, "NS", sendTo, "0");
                    Server.Send(c, responseXfr);
                }
                else
                {
                    Command response = new Command(Error.AuthenticationFailed, cmd.TrId);
                    Server.Send(c, response);
                }
            }
        }
 public DispatchController(DispatchConnection connection)
 {
     _connection = connection;
 }
Example #6
0
 protected virtual void HandleCvr(DispatchConnection c, Command cmd)
 {
     Msnp2Common.HandleCvr(Server, c, cmd);
 }
Example #7
0
            public IDbConnection Create(string connectionString, IDbConnectionFactory adapter, bool useCache = true)
            {
                if (string.IsNullOrEmpty(connectionString))
                {
                    throw new ArgumentException("数据库链接无效!", nameof(connectionString));
                }

                List <IDispatchConnection> connections = connectionCache.GetOrAdd(connectionString, _ => new List <IDispatchConnection>());

                if (useCache && connections.Count > 0)
                {
                    lock (connections)
                    {
                        foreach (var item in connections)
                        {
                            if (item.IsAlive && !item.IsActive)
                            {
                                return(item.ReuseConnection());
                            }
                        }
                    }
                }

                IDispatchConnection connection;

                if (adapter.MaxPoolSize == connections.Count && connections.RemoveAll(x => x.IsReleased) == 0)
                {
                    lock (connections)
                    {
                        connection = connections //? 线程已关闭的。
                                     .FirstOrDefault(x => !x.IsThreadActive) ?? connections
                                     .Where(x => !x.IsActive)
                                     .OrderBy(x => x.ActiveTime) //? 移除最长时间不活跃的链接。
                                     .FirstOrDefault() ?? throw new DException($"链接数超限(最大连接数:{adapter.MaxPoolSize})!");

                        return(connection.ReuseConnection());
                    }
                }

                var conn = adapter.Create(connectionString);

                if (conn is System.Data.Common.DbConnection dbConnection)
                {
                    connection = new DispatchConnection(dbConnection, adapter.ConnectionHeartbeat, useCache);
                }
                else
                {
                    connection = new DbConnection(conn, adapter.ConnectionHeartbeat, useCache);
                }

                lock (connections)
                {
                    connections.Add(connection);
                }

                if (!_clearTimerRun)
                {
                    _clearTimer.Start();
                    _clearTimerRun = true;
                }

                return(connection);
            }