/// <summary> /// Creates a socket and dispatches it and a message to a channel. /// </summary> protected Task Dispatch(Message message) { if (message == null) return Task.FromResult(0); var channel = Channel.MatchTopic(message.Topic); var socket = new Socket(this, _pubSub, channel, message.Topic); switch (message.Event) { case "phx_join": return JoinChannel(socket, message); case "phx_leave": return LeaveChannel(socket, message); case "heartbeat": return Heartbeat(socket, message); default: return DispatchMessage(socket, message); } }
public ArraySegment<byte> SerializeMessage(Message message) { var json = JsonConvert.SerializeObject(message, JsonSerializerSettings.Value); return new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)); }
/// <summary> /// Send a message to the socket. /// </summary> public virtual Task SendMessage(Message message) => SendByteArray(_socketSerializer.SerializeMessage(message));
/// <summary> /// Dispatches a message to a channel. /// </summary> /// <param name="message"></param> /// <returns></returns> protected static async Task DispatchMessage(Socket socket, Message message) { var eventResult = await socket.Channel.HandleIn(message, socket); switch(eventResult.ResultAction) { case EventResult.Action.NoReply: return; case EventResult.Action.Reply: await socket.Transport.SendReply(new Reply(message.Ref, message.Topic, eventResult.Status, eventResult.Response)); return; case EventResult.Action.Stop: // ?? return; } }
/// <summary> /// Converts a heartbeat message to a heartbeat reply. /// </summary> protected static Task Heartbeat(Socket socket, Message message) => socket.Transport.SendReply((new Reply(message.Ref, message.Topic, "ok", new JObject())));
protected static Task LeaveChannel(Socket socket, Message message) { return null; }
/// <summary> /// Subscribes to a channel topic. /// </summary> protected static Task JoinChannel(Socket socket, Message message) { JObject payload; string status; var joinResult = socket.Channel.Join(message.Topic, socket); if (joinResult.Success) { socket.PubSub.Subscribe(message.Topic, socket); status = "ok"; payload = joinResult.Response; } else { status = "error"; payload = new JObject(joinResult.Error); } return socket.Transport.SendReply(new Reply(message.Ref, message.Topic, status, payload)); }
internal async Task<EventResult> HandleIn(Message message, Socket socket) { var attr = _incomingEvents.Keys.FirstOrDefault(a => a.IsMatch(message.Event)); if (attr == null) throw new Exception($"Unable to route ${message.Event} to a channel incoming event hook in class ${GetType()}"); MethodInfo action; if (!_incomingEvents.TryGetValue(attr, out action)) throw new Exception($"Unable to get channel handle in hook for event {message.Event}."); return await (action.Invoke(this, new object[] { message.Payload, socket }) as Task<EventResult>); }