2020-03-25 16:42:30 +08:00
|
|
|
|
using System;
|
2020-04-23 12:07:30 +08:00
|
|
|
|
using System.Collections.Generic;
|
2020-03-25 16:42:30 +08:00
|
|
|
|
using System.Threading.Tasks;
|
2020-04-28 17:02:52 +08:00
|
|
|
|
using LeanCloud.Realtime.Internal.Protocol;
|
2020-03-25 16:42:30 +08:00
|
|
|
|
|
|
|
|
|
namespace LeanCloud.Realtime.Internal.Controller {
|
|
|
|
|
internal class LCIMSessionController : LCIMController {
|
|
|
|
|
private string token;
|
|
|
|
|
private DateTimeOffset expiredAt;
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
internal LCIMSessionController(LCIMClient client)
|
|
|
|
|
: base(client) {
|
2020-03-25 16:42:30 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
#region 内部接口
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 打开会话
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2020-04-16 11:38:22 +08:00
|
|
|
|
internal async Task Open(bool force) {
|
2020-04-23 12:07:30 +08:00
|
|
|
|
SessionCommand session = await NewSessionCommand();
|
2020-04-16 11:38:22 +08:00
|
|
|
|
session.R = !force;
|
2020-04-26 16:27:56 +08:00
|
|
|
|
session.ConfigBitmap = 0x2B;
|
2020-04-14 14:51:14 +08:00
|
|
|
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
|
|
|
|
request.SessionMessage = session;
|
|
|
|
|
GenericCommand response = await Client.Connection.SendRequest(request);
|
|
|
|
|
UpdateSession(response.SessionMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重新打开会话,重连时调用
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
internal async Task Reopen() {
|
2020-04-23 12:07:30 +08:00
|
|
|
|
SessionCommand session = await NewSessionCommand();
|
2020-04-14 14:51:14 +08:00
|
|
|
|
session.R = true;
|
|
|
|
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
2020-03-25 16:42:30 +08:00
|
|
|
|
request.SessionMessage = session;
|
|
|
|
|
GenericCommand response = await Client.Connection.SendRequest(request);
|
2020-04-14 15:28:01 +08:00
|
|
|
|
if (response.Op == OpType.Opened) {
|
|
|
|
|
UpdateSession(response.SessionMessage);
|
|
|
|
|
} else if (response.Op == OpType.Closed) {
|
|
|
|
|
await OnClosed(response.SessionMessage);
|
|
|
|
|
}
|
2020-03-25 16:42:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 关闭会话
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2020-03-25 16:42:30 +08:00
|
|
|
|
internal async Task Close() {
|
2020-04-14 14:51:14 +08:00
|
|
|
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Close);
|
2020-03-25 16:42:30 +08:00
|
|
|
|
await Client.Connection.SendRequest(request);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取可用 token
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2020-03-25 16:42:30 +08:00
|
|
|
|
internal async Task<string> GetToken() {
|
|
|
|
|
if (IsExpired) {
|
|
|
|
|
await Refresh();
|
|
|
|
|
}
|
|
|
|
|
return token;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
2020-03-25 16:42:30 +08:00
|
|
|
|
private async Task Refresh() {
|
2020-04-23 12:07:30 +08:00
|
|
|
|
SessionCommand session = await NewSessionCommand();
|
2020-04-14 14:51:14 +08:00
|
|
|
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Refresh);
|
2020-03-25 16:42:30 +08:00
|
|
|
|
request.SessionMessage = session;
|
|
|
|
|
GenericCommand response = await Client.Connection.SendRequest(request);
|
|
|
|
|
UpdateSession(response.SessionMessage);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-23 12:07:30 +08:00
|
|
|
|
private async Task<SessionCommand> NewSessionCommand() {
|
2020-03-25 16:42:30 +08:00
|
|
|
|
SessionCommand session = new SessionCommand();
|
2020-04-14 14:51:14 +08:00
|
|
|
|
if (Client.Tag != null) {
|
|
|
|
|
session.Tag = Client.Tag;
|
2020-04-16 11:38:22 +08:00
|
|
|
|
}
|
|
|
|
|
if (Client.DeviceId != null) {
|
|
|
|
|
session.DeviceId = Client.DeviceId;
|
2020-04-14 14:51:14 +08:00
|
|
|
|
}
|
2020-04-23 12:07:30 +08:00
|
|
|
|
LCIMSignature signature = null;
|
2020-03-25 16:42:30 +08:00
|
|
|
|
if (Client.SignatureFactory != null) {
|
2020-04-23 12:07:30 +08:00
|
|
|
|
signature = await Client.SignatureFactory.CreateConnectSignature(Client.Id);
|
|
|
|
|
}
|
|
|
|
|
if (signature == null && !string.IsNullOrEmpty(Client.SessionToken)) {
|
|
|
|
|
Dictionary<string, object> ret = await LCApplication.HttpClient.Post<Dictionary<string, object>>("rtm/sign", data: new Dictionary<string, object> {
|
|
|
|
|
{ "session_token", Client.SessionToken }
|
|
|
|
|
});
|
|
|
|
|
signature = new LCIMSignature {
|
|
|
|
|
Signature = ret["signature"] as string,
|
|
|
|
|
Timestamp = (long)ret["timestamp"],
|
|
|
|
|
Nonce = ret["nonce"] as string
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (signature != null) {
|
2020-03-25 16:42:30 +08:00
|
|
|
|
session.S = signature.Signature;
|
|
|
|
|
session.T = signature.Timestamp;
|
|
|
|
|
session.N = signature.Nonce;
|
|
|
|
|
}
|
|
|
|
|
return session;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateSession(SessionCommand session) {
|
|
|
|
|
token = session.St;
|
|
|
|
|
int ttl = session.StTtl;
|
|
|
|
|
expiredAt = DateTimeOffset.Now + TimeSpan.FromSeconds(ttl);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
private bool IsExpired {
|
|
|
|
|
get {
|
|
|
|
|
return DateTimeOffset.Now > expiredAt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 消息处理
|
|
|
|
|
|
2020-03-25 16:42:30 +08:00
|
|
|
|
internal override async Task OnNotification(GenericCommand notification) {
|
|
|
|
|
switch (notification.Op) {
|
|
|
|
|
case OpType.Closed:
|
|
|
|
|
await OnClosed(notification.SessionMessage);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 15:52:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 被关闭
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="session"></param>
|
|
|
|
|
/// <returns></returns>
|
2020-03-25 16:42:30 +08:00
|
|
|
|
private async Task OnClosed(SessionCommand session) {
|
|
|
|
|
int code = session.Code;
|
|
|
|
|
string reason = session.Reason;
|
|
|
|
|
string detail = session.Detail;
|
|
|
|
|
await Connection.Close();
|
2020-04-14 15:28:01 +08:00
|
|
|
|
Client.OnClose?.Invoke(code, reason);
|
2020-03-25 16:42:30 +08:00
|
|
|
|
}
|
2020-03-27 15:52:34 +08:00
|
|
|
|
|
|
|
|
|
#endregion
|
2020-03-25 16:42:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|