* LCIMChatRoom.cs:

* LCConnection.cs:
* LCIMController.cs:
* LCIMMessageController.cs:
* LCIMSessionController.cs:
* LCIMConversationController.cs:

* LCIMClient.cs: chore
oneRain 2020-04-14 14:51:14 +08:00
parent 88f2b64eba
commit bb3baf2ce8
7 changed files with 115 additions and 71 deletions

View File

@ -1,7 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using LeanCloud.Realtime.Protocol;
namespace LeanCloud.Realtime {
public class LCIMChatRoom : LCIMConversation {
@ -13,16 +11,8 @@ namespace LeanCloud.Realtime {
return await GetMembersCount();
}
public async Task<List<string>> GetOnlineMembers(int limit = 50) {
ConvCommand conv = new ConvCommand {
Cid = Id,
Limit = limit
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Members);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
List<string> memberList = response.ConvMessage.M.ToList();
return memberList;
public async Task<ReadOnlyCollection<string>> GetOnlineMembers(int limit = 50) {
return await Client.ConversationController.GetOnlineMembers(Id, limit);
}
}
}

View File

@ -14,12 +14,24 @@ namespace LeanCloud.Realtime.Internal.Connection {
/// 连接层,只与数据协议相关
/// </summary>
internal class LCConnection {
/// <summary>
/// 发送超时
/// </summary>
private const int SEND_TIMEOUT = 10000;
/// <summary>
/// 最大重连次数,超过后重置 Router 缓存后再次尝试重连
/// </summary>
private const int MAX_RECONNECT_TIMES = 3;
/// <summary>
/// 重连间隔
/// </summary>
private const int RECONNECT_INTERVAL = 5000;
/// <summary>
/// 心跳间隔
/// </summary>
private const int HEART_BEAT_INTERVAL = 5000;
internal Action<GenericCommand> OnNotification;

View File

@ -19,5 +19,19 @@ namespace LeanCloud.Realtime.Internal.Controller {
return Client.Connection;
}
}
protected GenericCommand NewCommand(CommandType cmd, OpType op) {
GenericCommand command = NewCommand(cmd);
command.Op = op;
return command;
}
protected GenericCommand NewCommand(CommandType cmd) {
return new GenericCommand {
Cmd = cmd,
AppId = LCApplication.AppId,
PeerId = Client.Id,
};
}
}
}

View File

@ -36,7 +36,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
bool temporary = false,
int temporaryTtl = 86400,
Dictionary<string, object> properties = null) {
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Start);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Start);
ConvCommand conv = new ConvCommand {
Transient = transient,
Unique = unique,
@ -99,7 +99,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
ConvCommand conv = new ConvCommand {
Cid = convId,
};
GenericCommand command = Client.NewCommand(CommandType.Conv, OpType.Count);
GenericCommand command = NewCommand(CommandType.Conv, OpType.Count);
command.ConvMessage = conv;
GenericCommand response = await Connection.SendRequest(command);
return response.ConvMessage.Count;
@ -120,7 +120,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Timestamp = message.SentTimestamp
};
read.Convs.Add(tuple);
GenericCommand request = Client.NewCommand(CommandType.Read, OpType.Open);
GenericCommand request = NewCommand(CommandType.Read, OpType.Open);
request.ReadMessage = read;
await Client.Connection.SendRequest(request);
}
@ -139,7 +139,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
conv.Attr = new JsonObjectMessage {
Data = JsonConvert.SerializeObject(attributes)
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Update);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Update);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
JsonObjectMessage attr = response.ConvMessage.AttrModified;
@ -173,7 +173,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
conv.T = signature.Timestamp;
conv.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Add);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Add);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
@ -203,7 +203,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
conv.T = signature.Timestamp;
conv.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Remove);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
@ -220,7 +220,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
ConvCommand conv = new ConvCommand {
Cid = convId
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Mute);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Mute);
request.ConvMessage = conv;
await Client.Connection.SendRequest(request);
}
@ -234,7 +234,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
ConvCommand conv = new ConvCommand {
Cid = convId
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Unmute);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Unmute);
request.ConvMessage = conv;
await Client.Connection.SendRequest(request);
}
@ -254,7 +254,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Cid = convId
};
conv.M.AddRange(clientIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.AddShutup);
GenericCommand request = NewCommand(CommandType.Conv, OpType.AddShutup);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
@ -272,7 +272,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Cid = convId
};
conv.M.AddRange(clientIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Remove);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
@ -299,7 +299,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
blacklist.T = signature.Timestamp;
blacklist.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Block);
GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Block);
request.BlacklistMessage = blacklist;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
@ -326,7 +326,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
blacklist.T = signature.Timestamp;
blacklist.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Unblock);
GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Unblock);
request.BlacklistMessage = blacklist;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
@ -350,7 +350,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Role = role
}
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
GenericCommand request = NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
}
@ -398,7 +398,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Limit = limit,
Next = next
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.QueryShutup);
GenericCommand request = NewCommand(CommandType.Conv, OpType.QueryShutup);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult {
@ -422,7 +422,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Limit = limit,
Next = next
};
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Query);
GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Query);
request.BlacklistMessage = black;
GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult {
@ -479,13 +479,18 @@ namespace LeanCloud.Realtime.Internal.Controller {
}).ToList().AsReadOnly();
}
/// <summary>
/// 获取临时对话
/// </summary>
/// <param name="convIds"></param>
/// <returns></returns>
internal async Task<List<LCIMTemporaryConversation>> GetTemporaryConversations(IEnumerable<string> convIds) {
if (convIds == null || convIds.Count() == 0) {
return null;
}
ConvCommand convMessage = new ConvCommand();
convMessage.TempConvIds.AddRange(convIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Query);
GenericCommand request = NewCommand(CommandType.Conv, OpType.Query);
request.ConvMessage = convMessage;
GenericCommand response = await Connection.SendRequest(request);
JsonObjectMessage results = response.ConvMessage.Results;
@ -498,11 +503,16 @@ namespace LeanCloud.Realtime.Internal.Controller {
return convList;
}
/// <summary>
/// 拉取对话接收/已读情况
/// </summary>
/// <param name="convId"></param>
/// <returns></returns>
internal async Task FetchReciptTimestamp(string convId) {
ConvCommand convCommand = new ConvCommand {
Cid = convId
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.MaxRead);
GenericCommand request = NewCommand(CommandType.Conv, OpType.MaxRead);
request.ConvMessage = convCommand;
GenericCommand response = await Connection.SendRequest(request);
convCommand = response.ConvMessage;
@ -511,6 +521,26 @@ namespace LeanCloud.Realtime.Internal.Controller {
conversation.LastReadTimestamp = convCommand.MaxReadTimestamp;
}
/// <summary>
/// 获取在线成员
/// </summary>
/// <param name="convId"></param>
/// <param name="limit"></param>
/// <returns></returns>
internal async Task<ReadOnlyCollection<string>> GetOnlineMembers(string convId,
int limit) {
ConvCommand conv = new ConvCommand {
Cid = convId,
Limit = limit
};
GenericCommand request = NewCommand(CommandType.Conv, OpType.Members);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
ReadOnlyCollection<string> members = response.ConvMessage.M
.ToList().AsReadOnly();
return members;
}
private LCIMPartiallySuccessResult NewPartiallySuccessResult(IEnumerable<string> succesfulIds,
IEnumerable<ErrorCommand> errors) {
LCIMPartiallySuccessResult result = new LCIMPartiallySuccessResult {

View File

@ -32,7 +32,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
} else {
throw new ArgumentException("Message MUST BE LCIMTypedMessage or LCIMBinaryMessage.");
}
GenericCommand command = Client.NewDirectCommand();
GenericCommand command = NewCommand(CommandType.Direct);
command.DirectMessage = direct;
GenericCommand response = await Client.Connection.SendRequest(command);
// 消息发送应答
@ -57,7 +57,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
Recall = true
};
patch.Patches.Add(item);
GenericCommand request = Client.NewCommand(CommandType.Patch, OpType.Modify);
GenericCommand request = NewCommand(CommandType.Patch, OpType.Modify);
request.PatchMessage = patch;
await Client.Connection.SendRequest(request);
}
@ -91,7 +91,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
item.MentionAll = newMessage.MentionAll;
}
patch.Patches.Add(item);
GenericCommand request = Client.NewCommand(CommandType.Patch, OpType.Modify);
GenericCommand request = NewCommand(CommandType.Patch, OpType.Modify);
request.PatchMessage = patch;
GenericCommand response = await Client.Connection.SendRequest(request);
}
@ -131,7 +131,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
if (messageType != 0) {
logs.Lctype = messageType;
}
GenericCommand request = Client.NewCommand(CommandType.Logs, OpType.Open);
GenericCommand request = NewCommand(CommandType.Logs, OpType.Open);
request.LogsMessage = logs;
GenericCommand response = await Client.Connection.SendRequest(request);
// TODO 反序列化聊天记录

View File

@ -18,9 +18,23 @@ namespace LeanCloud.Realtime.Internal.Controller {
/// 打开会话
/// </summary>
/// <returns></returns>
internal async Task Open() {
internal async Task Open(bool reconnect) {
SessionCommand session = NewSessionCommand();
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Open);
session.R = reconnect;
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() {
SessionCommand session = NewSessionCommand();
session.R = true;
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
request.SessionMessage = session;
GenericCommand response = await Client.Connection.SendRequest(request);
UpdateSession(response.SessionMessage);
@ -31,7 +45,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
/// </summary>
/// <returns></returns>
internal async Task Close() {
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Close);
GenericCommand request = NewCommand(CommandType.Session, OpType.Close);
await Client.Connection.SendRequest(request);
}
@ -50,7 +64,7 @@ namespace LeanCloud.Realtime.Internal.Controller {
private async Task Refresh() {
SessionCommand session = NewSessionCommand();
GenericCommand request = Client.NewCommand(CommandType.Session, OpType.Refresh);
GenericCommand request = NewCommand(CommandType.Session, OpType.Refresh);
request.SessionMessage = session;
GenericCommand response = await Client.Connection.SendRequest(request);
UpdateSession(response.SessionMessage);
@ -58,6 +72,10 @@ namespace LeanCloud.Realtime.Internal.Controller {
private SessionCommand NewSessionCommand() {
SessionCommand session = new SessionCommand();
if (Client.Tag != null) {
session.Tag = Client.Tag;
session.DeviceId = Guid.NewGuid().ToString();
}
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateConnectSignature(Client.Id);
session.S = signature.Signature;

View File

@ -19,6 +19,10 @@ namespace LeanCloud.Realtime {
get; private set;
}
public string Tag {
get; private set;
}
#region 事件
/// <summary>
@ -87,13 +91,6 @@ namespace LeanCloud.Realtime {
get; set;
}
/// <summary>
/// 客户端重连失败,连接成功,登录失败
/// </summary>
public Action OnReconnectError {
get; set;
}
/// <summary>
/// 用户在其他客户端登录,当前客户端被服务端强行下线
/// </summary>
@ -257,11 +254,15 @@ namespace LeanCloud.Realtime {
#region 接口
public LCIMClient(string clientId,
string tag = null,
ILCIMSignatureFactory signatureFactory = null) {
Id = clientId;
Tag = tag;
SignatureFactory = signatureFactory;
ConversationDict = new Dictionary<string, LCIMConversation>();
// 模块
SessionController = new LCIMSessionController(this);
ConversationController = new LCIMConversationController(this);
MessageController = new LCIMMessageController(this);
@ -280,10 +281,10 @@ namespace LeanCloud.Realtime {
/// 连接
/// </summary>
/// <returns></returns>
public async Task Open() {
public async Task Open(bool reconnect = false) {
await Connection.Connect();
// 打开 Session
await SessionController.Open();
await SessionController.Open(reconnect);
}
/// <summary>
@ -451,13 +452,14 @@ namespace LeanCloud.Realtime {
private async Task HandleReconnected() {
try {
// 打开 Session
await SessionController.Open();
await SessionController.Reopen();
// 回调用户
OnReconnected?.Invoke();
} catch (Exception e) {
LCLogger.Error(e);
await Connection.Close();
OnReconnectError?.Invoke();
// TODO 告知
//OnClose?.Invoke();
}
}
@ -468,27 +470,5 @@ namespace LeanCloud.Realtime {
conversation = await GetConversation(convId);
return conversation;
}
internal GenericCommand NewCommand(CommandType cmd, OpType op) {
GenericCommand command = NewCommand(cmd);
command.Op = op;
return command;
}
internal GenericCommand NewCommand(CommandType cmd) {
return new GenericCommand {
Cmd = cmd,
AppId = LCApplication.AppId,
PeerId = Id,
};
}
internal GenericCommand NewDirectCommand() {
return new GenericCommand {
Cmd = CommandType.Direct,
AppId = LCApplication.AppId,
PeerId = Id,
};
}
}
}