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; }
protected virtual void HandleCvr(DispatchConnection c, Command cmd) { Msnp2Common.HandleCvr(Server, c, cmd); }
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); }