diff --git a/LiveQuery/LiveQuery/Internal/LCLiveQueryConnection.cs b/LiveQuery/LiveQuery/Internal/LCLiveQueryConnection.cs index d2e4466..d11a33e 100644 --- a/LiveQuery/LiveQuery/Internal/LCLiveQueryConnection.cs +++ b/LiveQuery/LiveQuery/Internal/LCLiveQueryConnection.cs @@ -136,9 +136,9 @@ namespace LeanCloud.LiveQuery.Internal { await client.Close(); } - private void OnClientMessage(byte[] bytes) { + private void OnClientMessage(byte[] bytes, int length) { try { - string json = Encoding.UTF8.GetString(bytes); + string json = Encoding.UTF8.GetString(bytes, 0, length); Dictionary msg = JsonConvert.DeserializeObject>(json, LCJsonConverter.Default); LCLogger.Debug($"{id} <= {json}"); diff --git a/Realtime/Realtime-Unity/Realtime-Unity.csproj b/Realtime/Realtime-Unity/Realtime-Unity.csproj index c73c438..70af818 100644 --- a/Realtime/Realtime-Unity/Realtime-Unity.csproj +++ b/Realtime/Realtime-Unity/Realtime-Unity.csproj @@ -127,6 +127,6 @@ - + diff --git a/Realtime/Realtime/Conversation/LCIMConversation.cs b/Realtime/Realtime/Conversation/LCIMConversation.cs index f74ace8..ed6e75b 100644 --- a/Realtime/Realtime/Conversation/LCIMConversation.cs +++ b/Realtime/Realtime/Conversation/LCIMConversation.cs @@ -136,7 +136,10 @@ namespace LeanCloud.Realtime { /// public object this[string key] { get { - return customProperties[key]; + if (customProperties.TryGetValue(key, out object val)) { + return val; + } + return null; } set { customProperties[key] = value; diff --git a/Realtime/Realtime/Internal/Connection/LCConnection.cs b/Realtime/Realtime/Internal/Connection/LCConnection.cs index 8e3d1d5..5716a74 100644 --- a/Realtime/Realtime/Internal/Connection/LCConnection.cs +++ b/Realtime/Realtime/Internal/Connection/LCConnection.cs @@ -160,9 +160,9 @@ namespace LeanCloud.Realtime.Internal.Connection { } } - private void OnMessage(byte[] bytes) { + private void OnMessage(byte[] bytes, int length) { try { - GenericCommand command = GenericCommand.Parser.ParseFrom(bytes); + GenericCommand command = GenericCommand.Parser.ParseFrom(bytes, 0, length); LCLogger.Debug($"{id} <= {FormatCommand(command)}"); if (command.HasI) { // 应答 diff --git a/Realtime/Realtime/Internal/WebSocket/LCWebSocketClient.cs b/Realtime/Realtime/Internal/WebSocket/LCWebSocketClient.cs index 1a6e5e4..6c6456f 100644 --- a/Realtime/Realtime/Internal/WebSocket/LCWebSocketClient.cs +++ b/Realtime/Realtime/Internal/WebSocket/LCWebSocketClient.cs @@ -6,13 +6,15 @@ using System.Text; namespace LeanCloud.Realtime.Internal.WebSocket { public class LCWebSocketClient { // .net standard 2.0 好像在拼合 Frame 时有 bug,所以将这个值调整大一些 - private const int RECV_BUFFER_SIZE = 1024 * 5; + private const int SEND_BUFFER_SIZE = 1024 * 5; + private const int RECV_BUFFER_SIZE = 1024 * 8; + private const int MSG_BUFFER_SIZE = 1024 * 10; private const int CLOSE_TIMEOUT = 5000; private const int CONNECT_TIMEOUT = 10000; - public Action OnMessage; + public Action OnMessage; public Action OnClose; @@ -23,6 +25,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket { LCLogger.Debug($"Connecting WebSocket: {server}"); Task timeoutTask = Task.Delay(CONNECT_TIMEOUT); ws = new ClientWebSocket(); + ws.Options.SetBuffer(RECV_BUFFER_SIZE, SEND_BUFFER_SIZE); if (!string.IsNullOrEmpty(subProtocol)) { ws.Options.AddSubProtocol(subProtocol); } @@ -78,10 +81,12 @@ namespace LeanCloud.Realtime.Internal.WebSocket { } private async Task StartReceive() { - byte[] buffer = new byte[RECV_BUFFER_SIZE]; + byte[] recvBuffer = new byte[RECV_BUFFER_SIZE]; + byte[] msgBuffer = new byte[MSG_BUFFER_SIZE]; + int offset = 0; try { while (ws.State == WebSocketState.Open) { - WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment(buffer), default); + WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment(recvBuffer), default); if (result.MessageType == WebSocketMessageType.Close) { LCLogger.Debug($"Receive Closed: {result.CloseStatus}"); if (ws.State == WebSocketState.CloseReceived) { @@ -98,9 +103,18 @@ namespace LeanCloud.Realtime.Internal.WebSocket { } else { // 拼合 WebSocket Message int length = result.Count; - byte[] data = new byte[length]; - Array.Copy(buffer, data, length); - OnMessage?.Invoke(data); + if (offset + length > msgBuffer.Length) { + // 反序列化数组大小不够,则以 2x 扩充 + byte[] newBuffer = new byte[msgBuffer.Length * 2]; + Array.Copy(msgBuffer, newBuffer, msgBuffer.Length); + msgBuffer = newBuffer; + } + Array.Copy(recvBuffer, 0, msgBuffer, offset, length); + offset += length; + if (result.EndOfMessage) { + OnMessage?.Invoke(msgBuffer, offset); + offset = 0; + } } } } catch (Exception e) { diff --git a/Realtime/Realtime/Realtime.csproj b/Realtime/Realtime/Realtime.csproj index 537885a..a33af4f 100644 --- a/Realtime/Realtime/Realtime.csproj +++ b/Realtime/Realtime/Realtime.csproj @@ -8,7 +8,7 @@ - + diff --git a/Storage/Storage.Test/UserTest.cs b/Storage/Storage.Test/UserTest.cs index 7d1ba8b..99f320a 100644 --- a/Storage/Storage.Test/UserTest.cs +++ b/Storage/Storage.Test/UserTest.cs @@ -49,7 +49,7 @@ namespace Storage.Test { Assert.NotNull(current.ObjectId); Assert.IsFalse(current.EmailVerified); Assert.IsFalse(current.MobileVerified); - Assert.AreEqual(current.Mobile, "15101006008"); + Assert.AreEqual(current.Mobile, "15101006007"); } [Test] @@ -70,7 +70,7 @@ namespace Storage.Test { [Test] public async Task RelateObject() { - LCUser user = await LCUser.LoginByMobilePhoneNumber("15101006007", "112358"); + LCUser user = await LCUser.LoginByMobilePhoneNumber("15101006007", "world"); LCObject account = new LCObject("Account"); account["user"] = user; await account.Save(); diff --git a/Storage/Storage/LCObject.cs b/Storage/Storage/LCObject.cs index cdbd90f..0c302b2 100644 --- a/Storage/Storage/LCObject.cs +++ b/Storage/Storage/LCObject.cs @@ -125,7 +125,8 @@ namespace LeanCloud.Storage { if (key.StartsWith("_")) { throw new ArgumentException("key should not start with '_'"); } - if (key == "objectId" || key == "createdAt" || key == "updatedAt") { + if (key == "objectId" || key == "createdAt" || key == "updatedAt" || + key == "className") { throw new ArgumentException($"{key} is reserved by LeanCloud"); } LCSetOperation setOp = new LCSetOperation(value); diff --git a/Storage/Storage/LCUser.cs b/Storage/Storage/LCUser.cs index 4b20305..7a5b1dd 100644 --- a/Storage/Storage/LCUser.cs +++ b/Storage/Storage/LCUser.cs @@ -531,8 +531,8 @@ namespace LeanCloud.Storage { }; try { await Save(); - oriAuthData.Add(authType, data); - AuthData = oriAuthData; + oriAuthData[authType] = data; + UpdateAuthData(oriAuthData); } catch (Exception e) { AuthData = oriAuthData; throw e; @@ -547,13 +547,19 @@ namespace LeanCloud.Storage { try { await Save(); oriAuthData.Remove(authType); - AuthData = oriAuthData; + UpdateAuthData(oriAuthData); } catch (Exception e) { AuthData = oriAuthData; throw e; } } + private void UpdateAuthData(Dictionary authData) { + LCObjectData objData = new LCObjectData(); + objData.CustomPropertyDict["authData"] = authData; + Merge(objData); + } + static async Task Login(Dictionary data) { Dictionary response = await LCApplication.HttpClient.Post>("login", data: data); LCObjectData objectData = LCObjectData.Decode(response);