/// <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 SendMeshHandshake(this Connection channel) { // Acquire and set the handhshake packet var packet = MeshHandshake.Acquire(); packet.Key = Murmur32.GetHash(Service.Mesh.Cluster); packet.Identity = new GossipMember(Service.Mesh.BroadcastEndpoint); // Send the handshake packet channel.Send(packet); }
/// <summary> /// Handles the command. /// </summary> /// <param name="channel">The channel sending the command.</param> /// <param name="command">The command received.</param> private static void OnHandshake(Connection channel, MeshHandshake handshake) { // Deserialize the handshake var endpoint = handshake.Identity.EndPoint; var id = endpoint.ToIdentifier(); // Set the identifier of the channel channel.MeshIdentifier = id; // Validate the credentials if (!(Murmur32.GetHash(Service.Mesh.Cluster) == handshake.Key)) { throw new UnauthorizedAccessException("Cluster access was not authorized."); } // Check if we're trying to connect to ourselves if (Service.Mesh.Identifier == id) { // It's ourselves, remove from tracking //var ep = channel.RemoteEndPoint as IPEndPoint; var port = ((IPEndPoint)Service.Mesh.Binding.EndPoint).Port; var ep = new IPEndPoint(channel.RemoteEndPoint.Address, port); if (ep != null) { Service.Mesh.Members.ForgetPeer(ep); } channel.Close(); return; } // Attempt to register MeshMember node; if (Service.Mesh.Members.TryRegister(endpoint, channel, out node)) { // Send ACK first channel.SendMeshHandshakeAck(); // Send an event since we're connected to the node Service.InvokeNodeConnect(new ClusterEventArgs(node)); } else { channel.Close(); } }