private void HandleMessage(JObject msg) { ShareDBException ex = null; var error = (JObject)msg["error"]; if (error != null) { ex = new ShareDBException((string)error["message"], (int)error["code"]); } IDocumentInternal doc; switch ((string)msg["a"]) { case "init": if ((int)msg["protocol"] != 1) { _initTcs.SetException(new ShareDBException("Invalid protocol version.", 4019)); return; } if ((string)msg["type"] != "http://sharejs.org/types/JSONv0") { _initTcs.SetException(new ShareDBException("Invalid default type.", 4020)); return; } if (msg["id"].Type != JTokenType.String) { _initTcs.SetException(new ShareDBException("Invalid client id.", 4021)); return; } _id = (string)msg["id"]; _initTcs.SetResult(true); break; case "f": doc = GetExisting((string)msg["c"], (string)msg["d"]); var snapshot = (JObject)msg["data"]; doc.HandleFetch(ex, (int?)snapshot?["v"] ?? 0, (string)snapshot?["type"], snapshot?["data"]); break; case "op": doc = GetExisting((string)msg["c"], (string)msg["d"]); doc.HandleOp(ex, (int?)msg["v"] ?? 0, (int?)msg["seq"] ?? 0); break; } }
void IDocumentInternal.HandleOp(ShareDBException ex, int version, int seq) { OpInfo opInfo = _inflightOpInfo; _inflightOpInfo = null; if (ex != null) { if (ex.Code == 4002) { _inflightOp.SetResult(false); } else { _inflightOp.SetException(ex); } } else if (seq != opInfo.Seq || (opInfo.MessageType != OpMessageType.Create && version != Version)) { _inflightOp.SetException(new ShareDBException("Received incorrect op acknowledgement.", 4100)); } else { switch (opInfo.MessageType) { case OpMessageType.Create: Version = version; Data = (T)Type.Deserialize(opInfo.Op); IsLoaded = true; break; case OpMessageType.Op: Data = (T)Type.Apply(Data, opInfo.Op); IsLoaded = true; break; case OpMessageType.Delete: Data = default(T); IsLoaded = false; break; } Version++; _inflightOp.SetResult(true); } }
void IDocumentInternal.HandleFetch(ShareDBException ex, int version, string type, JToken ops) { if (!_inflightFetches.TryDequeue(out TaskCompletionSource <bool> tcs)) { return; } if (ex != null) { tcs.SetException(ex); } else { IOTType otType = null; if (type != null && !OTTypes.TryGetType(type, out otType)) { tcs.SetException(new ShareDBException($"Unregistered type {type}.", 4008)); } if (Type == null) { Type = otType; } if (otType != null && Type != otType) { tcs.SetException(new ShareDBException("The document type does not match the retrieved data type.", 4101)); } else { Version = version; if (ops != null) { Data = (T)Type.Deserialize(ops); IsLoaded = true; tcs.SetResult(true); } else { tcs.SetResult(false); } } } }