private async Task messageFrom(WebSocketConnection wsc, string msg) { ManagedConnection mc = null; lock (conns) { mc = conns.Find(x => x.WSC.Id == wsc.Id); } if (mc == null) { await wsc.CloseIfNotClosedAsync("Where did this websocket connection come from?"); return; } mc.LastActiveUtc = DateTime.UtcNow; // Diagnostic: see what happens when message handling code throws if (msg == "BOO") { throw new Exception("up"); } // Client announcing their session key as the first message if (msg.StartsWith("SESSIONKEY ")) { if (mc.SessionKey != null) { await wsc.CloseIfNotClosedAsync("Client already sent their session key"); return; } var sessionKey = msg.Substring(11); var startStr = docJuggler.StartSession(sessionKey); if (startStr == null) { await wsc.CloseIfNotClosedAsync("We're not expecting a session with this key"); return; } mc.SessionKey = sessionKey; await wsc.SendAsync("HELLO " + startStr, CancellationToken.None); return; } // Anything else: client must be past sessionkey check if (mc.SessionKey == null) { await wsc.CloseIfNotClosedAsync("Don't talk until you've announced your session key"); return; } // Just a keepalive ping: see if session is still open? if (msg == "PING") { if (!docJuggler.IsSessionOpen(mc.SessionKey)) { await wsc.CloseIfNotClosedAsync("This is not an open session"); } return; } // Client announced a change if (msg.StartsWith("CHANGE ")) { int ix1 = msg.IndexOf(' ', 7); int ix2 = msg.IndexOf(' ', ix1 + 1); if (ix2 == -1) { ix2 = msg.Length; } int revId = int.Parse(msg.Substring(7, ix1 - 7)); string selStr = msg.Substring(ix1 + 1, ix2 - ix1 - 1); string changeStr = null; if (ix2 != msg.Length) { changeStr = msg.Substring(ix2 + 1); } if (!docJuggler.ChangeReceived(mc.SessionKey, revId, selStr, changeStr)) { await wsc.CloseIfNotClosedAsync("We don't like this change; your session might have expired, the doc may be gone, or the change may be invalid."); } return; } // Anything else: No. await wsc.CloseIfNotClosedAsync("You shouldn't have said that"); }