/// <summary> /// Acquires an appropriate event envelope. /// </summary> /// <returns></returns> private static MeshEvent Create(MeshEventType type) { // Get the appropriate packet switch (type) { case MeshEventType.Error: case MeshEventType.Ping: case MeshEventType.PingAck: case MeshEventType.HandshakeAck: return(MeshEvent.Acquire()); case MeshEventType.Handshake: return(MeshHandshake.Acquire()); case MeshEventType.GossipDigest: case MeshEventType.GossipSince: case MeshEventType.GossipUpdate: return(MeshGossip.Acquire()); case MeshEventType.Subscribe: case MeshEventType.Unsubscribe: case MeshEventType.Custom: return(MeshEmitterEvent.Acquire()); default: throw new InvalidOperationException("Unknown mesh packet"); } }
/// <summary> /// Sends a mesh Handshake through the specified channel. /// </summary> /// <param name="channel">The channel to send the packet to.</param> internal static void SendMeshHandshakeAck(this Connection channel) { var provider = Service.Providers.Resolve <MeshProvider>(); if (provider == null) { return; } // Send the ack channel.Send(MeshEvent.Acquire(MeshEventType.HandshakeAck, provider.BroadcastEndpoint.ToString())); }
/// <summary> /// Handles the command. /// </summary> /// <param name="channel">The channel sending the command.</param> /// <param name="command">The command received.</param> private static void OnHandshakeAck(Connection channel, MeshEvent command) { // Attempt to register MeshMember node; IPEndPoint ep; if (!MeshMember.TryParseEndpoint(command.Value, out ep)) { Service.Logger.Log(LogLevel.Error, "Unable to parse endpoint: " + command.Value); channel.Close(); return; } // Register the endpoint if (Service.Mesh.Members.TryRegister(ep, channel, out node)) { // Send an event since we're connected to the node Service.InvokeNodeConnect(new ClusterEventArgs(node)); } else { channel.Close(); } }
/// <summary> /// Sends a mesh PingAck through the specified channel. /// </summary> /// <param name="channel">The channel to send the packet to.</param> internal static void SendMeshPingAck(this Connection channel) { // Send the ack channel.Send(MeshEvent.Acquire(MeshEventType.PingAck)); }
/// <summary> /// Sends a mesh ping through the specified channel. /// </summary> /// <param name="server">The channel to send the packet to.</param> internal static void SendMeshPing(this IServer server) { server.Send(MeshEvent.Acquire(MeshEventType.Ping)); }
/// <summary> /// Sends a mesh PingAck through the specified channel. /// </summary> /// <param name="channel">The channel to send the packet to.</param> /// <param name="ex">The exception to wrap.</param> internal static void SendMeshError(this Connection channel, Exception ex) { // Send the error back channel.Send(MeshEvent.Acquire(MeshEventType.Error, ex.Message)); }
/// <summary> /// Handles the custom commands, JSON-encoded. /// </summary> /// <param name="server">The server which is sending the command.</param> /// <param name="event">The event.</param> /// <returns>The processing state of the event.</returns> public abstract ProcessingState ProcessEvent(IServer server, MeshEvent @event);
/// <summary> /// Handles a command. /// </summary> public static ProcessingState Process(Connection channel, MeshEvent ev) { // Trace the operation number and the length of the packet //if (ev.Type != MeshEventType.Gossip) // NetTrace.WriteLine("Incoming " + ev.ToString(), channel, NetTraceCategory.Mesh); try { switch (ev.Type) { // Acknowledge the Heartbeat/Ping case MeshEventType.Ping: OnPing(channel); break; // Acknowledge the handshake case MeshEventType.Handshake: OnHandshake(channel, ev as MeshHandshake); break; // On the ack, the remote node sends its identifier to us case MeshEventType.HandshakeAck: OnHandshakeAck(channel, ev); break; // When a node receives a gossip digest case MeshEventType.GossipDigest: OnGossipDigest(channel, ev as MeshGossip); break; // When a node receives a gossip since request case MeshEventType.GossipSince: OnGossipSince(channel, ev as MeshGossip); break; // When a node receives a gossip update case MeshEventType.GossipUpdate: OnGossipUpdate(channel, ev as MeshGossip); break; // When a custom command is received case MeshEventType.Custom: default: var node = Service.Mesh.Members.Get(channel.MeshIdentifier); if (node == null) { break; } // Only invoke if we have a properly established connection Service.Mesh.OnEvent(node, ev); break; } } catch (Exception ex) { // Send the error back //Service.Logger.Log("Error On " + ev.ToString() + ": " + ex.Message); Service.Logger.Log(ex); channel.SendMeshError(ex); } // We do not need to process further, as we've handled the command return(ProcessingState.Success); }