示例#1
0
 public void Send(ZreMessage msg)
 {
     foreach (var peer in _peers)
     {
         peer.Value.Send(msg.Duplicate());
     }
 }
示例#2
0
        public void Send(ZreMessage msg)
        {
            if (_connected)
            {
                _sentSequence += 1;
                msg.Sequence = _sentSequence;

                if (_verbose)
                {
                    Trace.WriteLine(
                        string.Format(
                            "({0}) send {1} to peer={2} sequence={3}",
                            _origin,
                            msg.Id,
                            _name ?? "-",
                            msg.Sequence));
                }

                try
                {
                    msg.Send(_mailbox);
                }
                catch (Exception)
                {
                    if (_verbose)
                    {
                        Trace.WriteLine(
                            string.Format(
                                "({0}) disconnect from peer (EAGAIN): name={1}",
                                _origin,
                                _name ?? "-"));
                    }
                }
            }
        }
示例#3
0
        public bool MessageLost(ZreMessage msg)
        {
            if (_verbose)
            {
                Trace.WriteLine(
                    string.Format(
                        "({0}) recv {1} from peer={2} sequence={3}",
                        _origin,
                        msg.Id,
                        _name ?? "-",
                        msg.Sequence));
            }

            if (msg.Id == ZreMessageType.Hello)
            {
                _wantSequence = 1;
            }
            else
            {
                _wantSequence += 1;
            }

            if (_wantSequence != msg.Sequence)
            {
                Trace.WriteLine(
                    string.Format(
                        "({0}) seq error from peer={1} expect={2}, got={3}",
                        _origin,
                        _name ?? "-",
                        _wantSequence,
                        msg.Sequence));
                return true;
            }

            return false;
        }
示例#4
0
        public ZreMessage Duplicate()
        {
            ZreMessage clone = new ZreMessage(_id);

            if (_routingId != null)
            {
                clone._routingId = _routingId.Duplicate();
            }

            switch (_id)
            {
                case ZreMessageType.Hello:
                clone._version = _version;
                clone._sequence = _sequence;
                clone._endpoint = _endpoint;
                clone._groups = new HashSet<string>(_groups);
                clone._status = _status;
                clone._name = _name;
                clone._headers = new Dictionary<string, string>(_headers);
                break;
                case ZreMessageType.Whisper:
                clone._version = _version;
                clone._sequence = _sequence;
                clone._content = new NetMQMessage(_content.Select(x => x.Duplicate()));
                break;
                case ZreMessageType.Shout:
                clone._version = _version;
                clone._sequence = _sequence;
                clone._group = _group;
                clone._content = new NetMQMessage(_content.Select(x => x.Duplicate()));
                break;
                case ZreMessageType.Join:
                clone._version = _version;
                clone._sequence = _sequence;
                clone._group = _group;
                clone._status = _status;
                break;
                case ZreMessageType.Leave:
                clone._version = _version;
                clone._sequence = _sequence;
                clone._group = _group;
                clone._status = _status;
                break;
                case ZreMessageType.Ping:
                clone._version = _version;
                clone._sequence = _sequence;
                break;
                case ZreMessageType.PingOk:
                clone._version = _version;
                clone._sequence = _sequence;
                break;
            }

            return clone;
        }
示例#5
0
        public static bool IsZreMessage(NetMQMessage message)
        {
            if (message == null)
            {
                return false;
            }

            var frame = message.First;
            var msg = new ZreMessage(0);
            msg._needle = frame.ToByteArray();
            msg._needleReader = new BinaryReader(new MemoryStream(msg._needle));
            msg._needleWriter = new BinaryWriter(new MemoryStream(msg._needle));
            msg._ceiling = msg._needle.Length + frame.MessageSize;
            var signature = msg._needleReader.GetNumber2();
            if (signature != (0xAAA0 | ZreConstants.ProtocolSignature))
            {
                return false;
            }

            msg._id = (ZreMessageType)msg._needleReader.GetNumber1();

            switch (msg._id)
            {
                case ZreMessageType.Hello:
                case ZreMessageType.Whisper:
                case ZreMessageType.Shout:
                case ZreMessageType.Join:
                case ZreMessageType.Leave:
                case ZreMessageType.Ping:
                case ZreMessageType.PingOk:
                return true;
            }

            return false;
        }
示例#6
0
        public static NetMQMessage Encode(ZreMessage msg)
        {
            var message = new NetMQMessage();
            var frameSize = 2 + 1;  //  Signature and message ID

            switch (msg._id)
            {
                case ZreMessageType.Hello:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                //  endpoint is a string with 1-byte length
                frameSize++;       //  Size is one octet
                if (!string.IsNullOrEmpty(msg._endpoint))
                {
                    frameSize += msg._endpoint.Length;
                }
                //  groups is an array of strings
                frameSize += 4;    //  Size is 4 octets
                if (msg._groups != null && msg._groups.Count > 0)
                {
                    //  Add up size of list contents
                    foreach (var @group in msg._groups)
                    {
                        frameSize += 4 + @group.Length;
                    }
                }
                //  status is a 1-byte integer
                frameSize += 1;
                //  name is a string with 1-byte length
                frameSize++;       //  Size is one octet
                if (!string.IsNullOrEmpty(msg._name))
                {
                    frameSize += msg._name.Length;
                }
                //  headers is an array of key=value strings
                frameSize += 4;    //  Size is 4 octets
                if (msg._headers != null && msg._headers.Count > 0)
                {
                    msg._headersBytes = 0;
                    //  Add up size of dictionary contents
                    foreach (var header in msg._headers)
                    {
                        msg._headersBytes += 1 + header.Key.Length;
                        msg._headersBytes += 4 + header.Value.Length;
                    }
                }
                frameSize += msg._headersBytes;
                break;

                case ZreMessageType.Whisper:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                break;

                case ZreMessageType.Shout:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                //  group is a string with 1-byte length
                frameSize++;       //  Size is one octet
                if (!string.IsNullOrEmpty(msg._group))
                {
                    frameSize += msg._group.Length;
                }
                break;

                case ZreMessageType.Join:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                //  group is a string with 1-byte length
                frameSize++;       //  Size is one octet
                if (!string.IsNullOrEmpty(msg._group))
                {
                    frameSize += msg._group.Length;
                }
                //  status is a 1-byte integer
                frameSize += 1;
                break;

                case ZreMessageType.Leave:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                //  group is a string with 1-byte length
                frameSize++;       //  Size is one octet
                if (!string.IsNullOrEmpty(msg._group))
                {
                    frameSize += msg._group.Length;
                }
                //  status is a 1-byte integer
                frameSize += 1;
                break;

                case ZreMessageType.Ping:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                break;

                case ZreMessageType.PingOk:
                //  version is a 1-byte integer
                frameSize += 1;
                //  sequence is a 2-byte integer
                frameSize += 2;
                break;
            }

            var frame = new NetMQFrame(frameSize);
            msg._needle = frame.ToByteArray();
            msg._needleReader = new BinaryReader(new MemoryStream(msg._needle));
            msg._needleWriter = new BinaryWriter(new MemoryStream(msg._needle));
            msg._needleWriter.PutNumber2(0xAAA0 | ZreConstants.ProtocolSignature);
            msg._needleWriter.PutNumber1((byte)msg._id);
            switch (msg._id)
            {
                case ZreMessageType.Hello:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                if (!string.IsNullOrEmpty(msg._endpoint))
                {
                    msg._needleWriter.PutString(msg._endpoint);
                }
                else
                {
                    msg._needleWriter.PutNumber1(0);    //  Empty string
                }

                if (msg._groups != null)
                {
                    msg._needleWriter.PutNumber4(msg._groups.Count);
                    foreach (var @group in msg._groups)
                    {
                        msg._needleWriter.PutLongString(@group);
                    }
                }
                else
                {
                    msg._needleWriter.PutNumber4(0);    //  Empty string array
                }

                msg._needleWriter.PutNumber1(msg._status);

                if (!string.IsNullOrEmpty(msg._name))
                {
                    msg._needleWriter.PutString(msg._name);
                }
                else
                {
                    msg._needleWriter.PutNumber1(0);    //  Empty string
                }

                if (msg._headers != null)
                {
                    msg._needleWriter.PutNumber4(msg._headers.Count);
                    foreach (var header in msg._headers)
                    {
                        msg._needleWriter.PutString(header.Key);
                        msg._needleWriter.PutLongString(header.Value);
                    }
                }
                else
                {
                    msg._needleWriter.PutNumber4(0);    //  Empty dictionary
                }
                break;

                case ZreMessageType.Whisper:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                break;

                case ZreMessageType.Shout:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                if (!string.IsNullOrEmpty(msg._group))
                {
                    msg._needleWriter.PutString(msg._group);
                }
                else
                {
                    msg._needleWriter.PutNumber1(0);    //  Empty string
                }
                break;

                case ZreMessageType.Join:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                if (!string.IsNullOrEmpty(msg._group))
                {
                    msg._needleWriter.PutString(msg._group);
                }
                else
                {
                    msg._needleWriter.PutNumber1(0);    //  Empty string
                }
                msg._needleWriter.PutNumber1(msg._status);
                break;

                case ZreMessageType.Leave:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                if (!string.IsNullOrEmpty(msg._group))
                {
                    msg._needleWriter.PutString(msg._group);
                }
                else
                {
                    msg._needleWriter.PutNumber1(0);    //  Empty string
                }
                msg._needleWriter.PutNumber1(msg._status);
                break;

                case ZreMessageType.Ping:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                break;

                case ZreMessageType.PingOk:
                msg._needleWriter.PutNumber1(ZreConstants.ProtocolVersion);
                msg._needleWriter.PutNumber2(msg._sequence);
                break;
            }

            //  Now send the data frame
            message.Append(frame);

            //  Now send the message field if there is any
            if (msg._id == ZreMessageType.Whisper)
            {
                if (msg._content != null && !msg._content.IsEmpty)
                {
                    while (!msg._content.IsEmpty)
                    {
                        var contentFrame = msg._content.Pop();
                        message.Append(contentFrame);
                    }
                }
                else
                {
                    message.AppendEmptyFrame();
                }
            }
            //  Now send the message field if there is any
            if (msg._id == ZreMessageType.Shout)
            {
                if (msg._content != null && !msg._content.IsEmpty)
                {
                    while (!msg._content.IsEmpty)
                    {
                        var contentFrame = msg._content.Pop();
                        message.Append(contentFrame);
                    }
                }
                else
                {
                    message.AppendEmptyFrame();
                }
            }

            return message;
        }
示例#7
0
        public static ZreMessage Decode(NetMQMessage message)
        {
            var msg = new ZreMessage(0);
            var frame = message.Pop();
            if (frame == null)
            {
                return null;
            }

            msg._needle = frame.ToByteArray();
            msg._needleReader = new BinaryReader(new MemoryStream(msg._needle));
            msg._needleWriter = new BinaryWriter(new MemoryStream(msg._needle));
            msg._ceiling = msg._needle.Length + frame.MessageSize;
            var signature = msg._needleReader.GetNumber2();
            if (signature != (0xAAA0 | ZreConstants.ProtocolSignature))
            {
                return null;
            }

            msg._id = (ZreMessageType)msg._needleReader.GetNumber1();

            switch (msg._id)
            {
                case ZreMessageType.Hello:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                    msg._endpoint = msg._needleReader.GetString();

                    var listSize = msg._needleReader.GetNumber4();
                    msg._groups = new HashSet<string>();
                    while (listSize-- > 0)
                    {
                        var groupName = msg._needleReader.GetLongString();
                        msg._groups.Add(groupName);
                    }
                    msg._status = msg._needleReader.GetNumber1();
                    msg._name = msg._needleReader.GetString();

                    var hashSize = msg._needleReader.GetNumber4();
                    msg._headers = new ConcurrentDictionary<string, string>();
                    while (hashSize-- > 0)
                    {
                        var key = msg._needleReader.GetString();
                        var value = msg._needleReader.GetLongString();
                        msg._headers.Add(key, value);
                    }
                }
                break;
                case ZreMessageType.Whisper:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                    //  Get zero or more remaining frames, leaving current
                    //  frame untouched
                    msg._content = new NetMQMessage();
                    while (!message.IsEmpty)
                    {
                        msg._content.Append(message.Pop());
                    }

                    if (msg._content.IsEmpty)
                    {
                        msg._content.AppendEmptyFrame();
                    }
                }
                break;
                case ZreMessageType.Shout:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                    msg._group = msg._needleReader.GetString();
                    //  Get zero or more remaining frames, leaving current
                    //  frame untouched
                    msg._content = new NetMQMessage();
                    while (!message.IsEmpty)
                    {
                        msg._content.Append(message.Pop());
                    }

                    if (msg._content.IsEmpty)
                    {
                        msg._content.AppendEmptyFrame();
                    }
                }
                break;
                case ZreMessageType.Join:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                    msg._group = msg._needleReader.GetString();
                    msg._status = msg._needleReader.GetNumber1();
                }
                break;
                case ZreMessageType.Leave:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                    msg._group = msg._needleReader.GetString();
                    msg._status = msg._needleReader.GetNumber1();
                }
                break;
                case ZreMessageType.Ping:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                }
                break;
                case ZreMessageType.PingOk:
                {
                    msg._version = msg._needleReader.GetNumber1();
                    if (msg._version != ZreConstants.ProtocolVersion)
                    {
                        return null;
                    }
                    msg._sequence = msg._needleReader.GetNumber2();
                }
                break;
            }

            return msg;
        }
示例#8
0
        private ZrePeer RequirePeer(Guid identity, string endpoint)
        {
            ZrePeer peer;
            if (_peers.TryGetValue(identity, out peer))
            {
                return peer;
            }

            //  Purge any previous peer on same endpoint
            PurgePeer(endpoint);

            peer = new ZrePeer(_context, identity);
            _peers.TryAdd(identity, peer);
            peer.Origin = _name;
            peer.Verbose = _verbose;
            peer.Connect(_identity, endpoint);

            // Handshake discovery by sending HELLO as first message
            var groups = _ownGroups.Keys.ToArray();
            var headers = new ConcurrentDictionary<string, string>(_headers);
            var msg = new ZreMessage(ZreMessageType.Hello);
            msg.Endpoint = _endpoint;
            msg.Groups.UnionWith(groups);
            msg.Status = _status;
            msg.Name = _name;
            msg.Headers = headers;
            peer.Send(msg);

            return peer;
        }
示例#9
0
        private void OnPipeReady(object sender, NetMQSocketEventArgs e)
        {
            //  Get the whole message off the pipe in one go
            var message = e.Socket.ReceiveMultipartMessage();
            if (message == null)
            {
                return;
            }

            var command = message.Pop().ConvertToString();
            switch (command)
            {
                case Zre.StartCommand:
                if (Start())
                {
                    e.Socket.SignalOK();
                }
                else
                {
                    e.Socket.SignalError();
                }
                break;
                case Zre.StopCommand:
                if (Stop())
                {
                    e.Socket.SignalOK();
                }
                else
                {
                    e.Socket.SignalError();
                }
                break;
                case Zre.SetNameCommand:
                _name = message.Pop().ConvertToString();
                break;
                case Zre.GetNameCommand:
                _pipe.SendFrame(_name);
                break;
                case Zre.SetUuidCommand:
                _identity = new Guid(message.Pop().ToByteArray());
                break;
                case Zre.GetUuidCommand:
                _pipe.SendFrame(_identity.ToString());
                break;
                case Zre.SetIntervalCommand:
                _interval = TimeSpan.FromMilliseconds(message.Pop().ConvertToInt32());
                break;
                case Zre.SetVerboseCommand:
                _verbose = true;
                break;
                case Zre.SetHeaderCommand:
                {
                    var key = message.Pop().ConvertToString();
                    var value = message.Pop().ConvertToString();
                    _headers[key] = value;
                }
                break;
                case Zre.SetPortCommand:
                _beaconPort = message.Pop().ConvertToInt32();
                break;
                case Zre.WhisperCommand:
                {
                    //  Get peer to send message to
                    var identityString = message.Pop().ConvertToString();
                    Guid identity;
                    if (Guid.TryParse(identityString, out identity))
                    {
                        //  Send frame on out to peer's mailbox, drop message
                        //  if peer doesn't exist (may have been destroyed)
                        ZrePeer peer;
                        if (_peers.TryGetValue(identity, out peer))
                        {
                            var msg = new ZreMessage(ZreMessageType.Whisper);
                            msg.Content = message;
                            peer.Send(msg);
                        }
                    }
                }
                break;
                case Zre.ShoutCommand:
                {
                    //  Get group to send message to
                    var groupName = message.Pop().ConvertToString();
                    ZreGroup group;
                    if (_peerGroups.TryGetValue(groupName, out group))
                    {
                        var msg = new ZreMessage(ZreMessageType.Shout);
                        msg.Group = groupName;
                        msg.Content = message;
                        group.Send(msg);
                    }
                }
                break;
                case Zre.JoinCommand:
                {
                    var groupName = message.Pop().ConvertToString();
                    ZreGroup @group;
                    if (!_ownGroups.TryGetValue(groupName, out group))
                    {
                        @group = new ZreGroup(groupName);
                        _ownGroups[groupName] = @group;
                        var joinMsg = new ZreMessage(ZreMessageType.Join);
                        joinMsg.Group = groupName;
                        joinMsg.Status = ++_status;
                        foreach (var zrePeer in _peers)
                        {
                            zrePeer.Value.Send(joinMsg.Duplicate());
                        }

                        if (_verbose)
                        {
                            Trace.WriteLine(string.Format("({0}) JOIN group={1}", _name, groupName));
                        }
                    }
                }
                break;
                case Zre.LeaveCommand:
                {
                    var groupName = message.Pop().ConvertToString();
                    ZreGroup @group;
                    if (_ownGroups.TryGetValue(groupName, out group))
                    {
                        var leaveMsg = new ZreMessage(ZreMessageType.Leave);
                        leaveMsg.Group = groupName;
                        leaveMsg.Status = ++_status;
                        foreach (var zrePeer in _peers)
                        {
                            zrePeer.Value.Send(leaveMsg.Duplicate());
                        }

                        _ownGroups.TryRemove(groupName, out @group);

                        if (_verbose)
                        {
                            Trace.WriteLine(string.Format("({0}) LEAVE group={1}", _name, groupName));
                        }
                    }
                }
                break;
                case Zre.GetPeersCommand:
                {
                    var peerNames = _peers.Keys.ToArray();

                    using (var msgStream = new MemoryStream())
                    using (var writer = new BinaryWriter(msgStream))
                    {
                        foreach (var peerName in peerNames)
                        {
                            writer.PutString(peerName.ToString());
                        }

                        _pipe.SendFrame(msgStream.ToArray());
                    }
                }
                break;
                case Zre.GetPeerGroupsCommand:
                {
                }
                break;
                case Zre.GetOwnGroupsCommand:
                {
                }
                break;
                case Zre.GetPeerEndpointCommand:
                {
                    var identityString = message.Pop().ConvertToString();
                    Guid identity;
                    if (Guid.TryParse(identityString, out identity))
                    {
                        ZrePeer peer;
                        if (_peers.TryGetValue(identity, out peer))
                        {
                            _pipe.SendFrame(peer.Endpoint);
                        }
                    }
                }
                break;
                case Zre.GetPeerHeaderCommand:
                {
                    var identityString = message.Pop().ConvertToString();
                    var key = message.Pop().ConvertToString();
                    Guid identity;
                    if (Guid.TryParse(identityString, out identity))
                    {
                        ZrePeer peer;
                        if (_peers.TryGetValue(identity, out peer))
                        {
                            var header = peer.GetHeader(key, defaultValue: string.Empty);
                            _pipe.SendFrame(header);
                        }
                        else
                        {
                            _pipe.SendFrame(string.Empty);
                        }
                    }
                }
                break;
                case Zre.SetEndPointCommand:
                {
                    StartGossip();
                    var endpoint = message.Pop().ConvertToString();
                    try
                    {
                        _inbox.Bind(endpoint);
                        _endpoint = endpoint;
                        _pipe.SignalOK();
                    }
                    catch (Exception)
                    {
                        _pipe.SignalError();
                    }
                }
                break;
                case Zre.GossipBindCommand:
                {
                    StartGossip();
                    _gossipBind = message.Pop().ConvertToString();
                    _gossip.SendMoreFrame("BIND").SendFrame(_gossipBind);
                }
                break;
                case Zre.GossipConnectCommand:
                {
                    StartGossip();
                    _gossipConnect = message.Pop().ConvertToString();
                    _gossip.SendMoreFrame("CONNECT").SendFrame(_gossipConnect);
                }
                break;
                case Zre.SetInterfaceCommand:
                {
                    _beaconInterfaceName = message.Pop().ConvertToString();
                }
                break;
                case NetMQActor.EndShimMessage:
                _poller.Cancel();
                break;
            }
        }
示例#10
0
        private void OnPingPeer(object sender, NetMQTimerEventArgs e)
        {
            foreach (var peer in _peers.Values)
            {
                var clockTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                if (clockTime >= peer.ExpiredAt)
                {
                    if (_verbose)
                    {
                        Trace.WriteLine(
                            string.Format(
                                "({0}) peer expired name={1} endpoint={2}",
                                _name,
                                peer.Name,
                                peer.Endpoint));
                    }

                    RemovePeer(peer);
                }
                else if (clockTime >= peer.EvasiveAt)
                {
                    //  If peer is being evasive, force a TCP ping.
                    //  TODO: do this only once for a peer in this state;
                    //  it would be nicer to use a proper state machine
                    //  for peer management.
                    if (_verbose)
                    {
                        Trace.WriteLine(
                            string.Format(
                                "({0}) peer seems dead/slow name={1} endpoint={2}",
                                _name,
                                peer.Name,
                                peer.Endpoint));
                    }

                    var ping = new ZreMessage(ZreMessageType.Ping);
                    peer.Send(ping);

                    // Inform the calling application this peer is being evasive
                    _pipe
                        .SendMoreFrame("EVASIVE")
                        .SendMoreFrame(peer.Identity.ToString())
                        .SendFrame(peer.Name);
                }
            }
        }
示例#11
0
        private void OnInboxReady(object sender, NetMQSocketEventArgs e)
        {
            var msg = ZreMessage.Receive(e.Socket);
            if (msg == null)
            {
                return;
            }

            if (msg.RoutingId.MessageSize != ZreConstants.ZreUuidLength)
            {
                return;
            }

            // Router socket tells us the identity of this peer
            // Identity must be [1] followed by 16-byte UUID, ignore the [1]
            var uuidBuffer = new byte[16];
            var uuidReceived = msg.RoutingId.ToByteArray();
            Array.Copy(uuidReceived, 1, uuidBuffer, 0, uuidBuffer.Length);
            var senderId = new Guid(uuidBuffer);

            //  On HELLO we may create the peer if it's unknown
            //  On other commands the peer must already exist
            ZrePeer peer;
            _peers.TryGetValue(senderId, out peer);
            if (msg.Id == ZreMessageType.Hello)
            {
                if (peer != null)
                {
                    //  Remove fake peers
                    if (peer.Ready)
                    {
                        RemovePeer(peer);
                    }
                    else if (peer.Endpoint == _endpoint)
                    {
                        //  We ignore HELLO, if peer has same endpoint as current node
                        return;
                    }
                }

                peer = RequirePeer(senderId, msg.Endpoint);
                peer.Ready = true;
            }

            if (peer == null || !peer.Ready)
            {
                return;
            }

            if (peer.MessageLost(msg))
            {
                Trace.WriteLine(string.Format("({0}) messages lost from {1}", _name, peer.Name));
                RemovePeer(peer);
                return;
            }

            //  Now process each command
            if (msg.Id == ZreMessageType.Hello)
            {
                //  Store properties from HELLO command into peer
                peer.Name = msg.Name;
                peer.Headers = msg.Headers;

                //  Tell the caller about the peer
                _pipe
                    .SendMoreFrame("ENTER")
                    .SendMoreFrame(peer.Identity.ToString())
                    .SendMoreFrame(peer.Name)
                    .SendMoreFrame(peer.Headers.PackHeaders())
                    .SendFrame(msg.Endpoint);

                if (_verbose)
                {
                    Trace.WriteLine(
                        string.Format(
                            "({0}) ENTER name={1} endpoint={2}",
                            _name,
                            peer.Name,
                            peer.Endpoint));
                }

                //  Join peer to listed groups
                foreach (var @group in msg.Groups)
                {
                    JoinPeerGroup(peer, @group);
                }

                //  Now take peer's status from HELLO, after joining groups
                peer.Status = msg.Status;
            }
            else if (msg.Id == ZreMessageType.Whisper)
            {
                //  Pass up to caller API as WHISPER event
                _pipe
                    .SendMoreFrame(Zre.WhisperCommand)
                    .SendMoreFrame(senderId.ToString())
                    .SendMoreFrame(peer.Name)
                    .SendMultipartMessage(msg.Content);
            }
            else if (msg.Id == ZreMessageType.Shout)
            {
                //  Pass up to caller API as SHOUT event
                _pipe
                    .SendMoreFrame(Zre.ShoutCommand)
                    .SendMoreFrame(senderId.ToString())
                    .SendMoreFrame(peer.Name)
                    .SendMoreFrame(msg.Group)
                    .SendMultipartMessage(msg.Content);
            }
            else if (msg.Id == ZreMessageType.Ping)
            {
                var pong = new ZreMessage(ZreMessageType.PingOk);
                peer.Send(pong);
            }
            else if (msg.Id == ZreMessageType.Join)
            {
                JoinPeerGroup(peer, msg.Group);
            }
            else if (msg.Id == ZreMessageType.Leave)
            {
                LeavePeerGroup(peer, msg.Group);
            }

            //  Activity from peer resets peer timers
            peer.Refresh();
        }