private bool IdentifyPeer(Pipe pipe) { byte[] identity; if (m_options.RawSocket) { // Always assign identity for raw-socket identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); } else { // Pick up handshake cases and also case where next identity is set var msg = new Msg(); msg.InitEmpty(); bool ok = pipe.Read(ref msg); if (!ok) { return(false); } if (msg.Size == 0) { // Fall back on the auto-generation identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); msg.Close(); } else { identity = msg.CloneData(); // Ignore peers with duplicate ID. if (m_outpipes.ContainsKey(identity)) { msg.Close(); return(false); } msg.Close(); } } pipe.Identity = identity; // Add the record into output pipes lookup table var outpipe = new Outpipe(pipe, true); m_outpipes.Add(identity, outpipe); return(true); }
/// <summary> /// Indicate the given pipe as being ready for reading by this socket. /// </summary> /// <param name="pipe">the <c>Pipe</c> that is now becoming available for reading</param> protected override void XReadActivated(Pipe pipe) { // There are some subscriptions waiting. Let's process them. var sub = new Msg(); while (pipe.Read(ref sub)) { // Apply the subscription to the trie. byte[] data = sub.Data; int size = sub.Size; if (size > 0 && (data[0] == 0 || data[0] == 1)) { if (m_manual) { m_lastPipe = pipe; m_pending.Enqueue(sub.CloneData()); } else { var unique = data[0] == 0 ? m_subscriptions.Remove(data, 1, size - 1, pipe) : m_subscriptions.Add(data, 1, size - 1, pipe); // If the subscription is not a duplicate, store it so that it can be // passed to used on next recv call. if (m_options.SocketType == ZmqSocketType.Xpub && (unique || m_verbose)) { m_pending.Enqueue(sub.CloneData()); } } } else // process message unrelated to sub/unsub { m_pending.Enqueue(sub.CloneData()); } sub.Close(); } }
private bool IdentifyPeer([NotNull] Pipe pipe) { byte[] identity; if (m_options.RawSocket) { // Always assign identity for raw-socket identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); } else { // Pick up handshake cases and also case where next identity is set var msg = new Msg(); msg.InitEmpty(); bool ok = pipe.Read(ref msg); if (!ok) { return(false); } if (msg.Size == 0) { // Fall back on the auto-generation identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); msg.Close(); } else { identity = msg.CloneData(); msg.Close(); Outpipe existPipe; if (m_outpipes.TryGetValue(identity, out existPipe)) { if (!m_handover) { // Ignore peers with duplicate ID. return(false); } else { // We will allow the new connection to take over this // identity. Temporarily assign a new identity to the // existing pipe so we can terminate it asynchronously. var newIdentity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, newIdentity, 1, 4); existPipe.Pipe.Identity = newIdentity; m_outpipes.Add(newIdentity, existPipe); // Remove the existing identity entry to allow the new // connection to take the identity. m_outpipes.Remove(identity); if (existPipe.Pipe == m_currentIn) { m_closingCurrentIn = true; } else { existPipe.Pipe.Terminate(true); } } } } } pipe.Identity = identity; // Add the record into output pipes lookup table var outpipe = new Outpipe(pipe, true); m_outpipes.Add(identity, outpipe); return(true); }
/// <summary> /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending. /// </summary> /// <param name="msg">the message to transmit</param> /// <returns><c>true</c> if the message was sent successfully</returns> /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception> protected override bool XSend(ref Msg msg) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (!m_moreOut) { Debug.Assert(m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. // TODO: The connections should be killed instead. if (msg.HasMore) { m_moreOut = true; // Find the pipe associated with the identity stored in the prefix. // If there's no such pipe just silently ignore the message, unless // mandatory is set. var identity = msg.Size == msg.Data.Length ? msg.Data : msg.CloneData(); Outpipe op; if (m_outpipes.TryGetValue(identity, out op)) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite()) { op.Active = false; m_currentOut = null; if (m_mandatory) { m_moreOut = false; return(false); } } } else if (m_mandatory) { m_moreOut = false; throw new HostUnreachableException("In Router.XSend"); } } // Detach the message from the data buffer. msg.Close(); msg.InitEmpty(); return(true); } if (m_options.RawSocket) { msg.ResetFlags(MsgFlags.More); } // Check whether this is the last part of the message. m_moreOut = msg.HasMore; // Push the message into the pipe. If there's no out pipe, just drop it. if (m_currentOut != null) { // Close the remote connection if user has asked to do so // by sending zero length message. // Pending messages in the pipe will be dropped (on receiving term-ack) if (m_rawSocket && msg.Size == 0) { m_currentOut.Terminate(false); msg.Close(); msg.InitEmpty(); m_currentOut = null; return(true); } bool ok = m_currentOut.Write(ref msg); if (!ok) { m_currentOut = null; } else if (!m_moreOut) { m_currentOut.Flush(); m_currentOut = null; } } else { msg.Close(); } // Detach the message from the data buffer. msg.InitEmpty(); return(true); }
/// <summary> /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending. /// </summary> /// <param name="msg">the message to transmit</param> /// <returns><c>true</c> if the message was sent successfully</returns> /// <exception cref="HostUnreachableException">In Stream.XSend</exception> protected override bool XSend(ref Msg msg) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (!this.m_moreOut) { Debug.Assert(this.m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. // TODO: The connections should be killed instead. if (msg.HasMore) { // Find the pipe associated with the identity stored in the prefix. // If there's no such pipe just silently ignore the message, unless // mandatory is set. byte[] identity = msg.Size == msg.Data.Length ? msg.Data : msg.CloneData(); Outpipe op; if (this.m_outpipes.TryGetValue(identity, out op)) { this.m_currentOut = op.Pipe; if (!this.m_currentOut.CheckWrite()) { op.Active = false; this.m_currentOut = null; return(false); } } else { throw new HostUnreachableException("In Stream.XSend"); } } this.m_moreOut = true; msg.Close(); msg.InitEmpty(); return(true); } // Ignore the MORE flag msg.ResetFlags(MsgFlags.More); // This is the last part of the message. this.m_moreOut = false; // Push the message into the pipe. If there's no out pipe, just drop it. if (this.m_currentOut != null) { if (msg.Size == 0) { this.m_currentOut.Terminate(false); this.m_currentOut = null; return(true); } bool ok = this.m_currentOut.Write(ref msg); if (ok) { this.m_currentOut.Flush(); } this.m_currentOut = null; } // Detach the message from the data buffer. msg.InitEmpty(); return(true); }
private bool IdentifyPeer( Pipe pipe) { byte[] identity; if (m_options.RawSocket) { // Always assign identity for raw-socket identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); } else { // Pick up handshake cases and also case where next identity is set var msg = new Msg(); msg.InitEmpty(); bool ok = pipe.Read(ref msg); if (!ok) return false; if (msg.Size == 0) { // Fall back on the auto-generation identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); msg.Close(); } else { identity = msg.CloneData(); // Ignore peers with duplicate ID. if (m_outpipes.ContainsKey(identity)) { msg.Close(); return false; } msg.Close(); } } pipe.Identity = identity; // Add the record into output pipes lookup table var outpipe = new Outpipe(pipe, true); m_outpipes.Add(identity, outpipe); return true; }
/// <summary> /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending. /// </summary> /// <param name="msg">the message to transmit</param> /// <returns><c>true</c> if the message was sent successfully</returns> /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception> protected override bool XSend(ref Msg msg) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (!m_moreOut) { Debug.Assert(m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. // TODO: The connections should be killed instead. if (msg.HasMore) { m_moreOut = true; // Find the pipe associated with the identity stored in the prefix. // If there's no such pipe just silently ignore the message, unless // mandatory is set. var identity = msg.Size == msg.Data.Length ? msg.Data : msg.CloneData(); Outpipe op; if (m_outpipes.TryGetValue(identity, out op)) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite()) { op.Active = false; m_currentOut = null; if (m_mandatory) { m_moreOut = false; return false; } } } else if (m_mandatory) { m_moreOut = false; throw new HostUnreachableException("In Router.XSend"); } } // Detach the message from the data buffer. msg.Close(); msg.InitEmpty(); return true; } if (m_options.RawSocket) { msg.ResetFlags(MsgFlags.More); } // Check whether this is the last part of the message. m_moreOut = msg.HasMore; // Push the message into the pipe. If there's no out pipe, just drop it. if (m_currentOut != null) { // Close the remote connection if user has asked to do so // by sending zero length message. // Pending messages in the pipe will be dropped (on receiving term-ack) if (m_rawSocket && msg.Size == 0) { m_currentOut.Terminate(false); msg.Close(); msg.InitEmpty(); m_currentOut = null; return true; } bool ok = m_currentOut.Write(ref msg); if (!ok) m_currentOut = null; else if (!m_moreOut) { m_currentOut.Flush(); m_currentOut = null; } } else { msg.Close(); } // Detach the message from the data buffer. msg.InitEmpty(); return true; }
/// <summary> /// Indicate the given pipe as being ready for reading by this socket. /// </summary> /// <param name="pipe">the <c>Pipe</c> that is now becoming available for reading</param> protected override void XReadActivated(Pipe pipe) { // There are some subscriptions waiting. Let's process them. var sub = new Msg(); while (pipe.Read(ref sub)) { // Apply the subscription to the trie. byte[] data = sub.Data; int size = sub.Size; if (size > 0 && (data[0] == 0 || data[0] == 1)) { if (m_manual) { m_lastPipe = pipe; m_pending.Enqueue(sub.CloneData()); } else { var unique = data[0] == 0 ? m_subscriptions.Remove(data, 1, size - 1, pipe) : m_subscriptions.Add(data, 1, size - 1, pipe); // If the subscription is not a duplicate, store it so that it can be // passed to used on next recv call. if (m_options.SocketType == ZmqSocketType.Xpub && (unique || m_verbose)) m_pending.Enqueue(sub.CloneData()); } } else // process message unrelated to sub/unsub { m_pending.Enqueue(sub.CloneData()); } sub.Close(); } }
private bool IdentifyPeer([NotNull] Pipe pipe) { byte[] identity; if (m_options.RawSocket) { // Always assign identity for raw-socket identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); } else { // Pick up handshake cases and also case where next identity is set var msg = new Msg(); msg.InitEmpty(); bool ok = pipe.Read(ref msg); if (!ok) return false; if (msg.Size == 0) { // Fall back on the auto-generation identity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, identity, 1, 4); msg.Close(); } else { identity = msg.CloneData(); msg.Close(); Outpipe existPipe; if (m_outpipes.TryGetValue(identity, out existPipe)) { if (!m_handover) { // Ignore peers with duplicate ID. return false; } else { // We will allow the new connection to take over this // identity. Temporarily assign a new identity to the // existing pipe so we can terminate it asynchronously. var newIdentity = new byte[5]; byte[] result = BitConverter.GetBytes(m_nextPeerId++); Buffer.BlockCopy(result, 0, newIdentity, 1, 4); existPipe.Pipe.Identity = newIdentity; m_outpipes.Add(newIdentity, existPipe); // Remove the existing identity entry to allow the new // connection to take the identity. m_outpipes.Remove(identity); if (existPipe.Pipe == m_currentIn) m_closingCurrentIn = true; else existPipe.Pipe.Terminate(true); } } } } pipe.Identity = identity; // Add the record into output pipes lookup table var outpipe = new Outpipe(pipe, true); m_outpipes.Add(identity, outpipe); return true; }
/// <summary> /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending. /// </summary> /// <param name="msg">the message to transmit</param> /// <returns><c>true</c> if the message was sent successfully</returns> /// <exception cref="HostUnreachableException">In Stream.XSend</exception> protected override bool XSend(ref Msg msg) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (!m_moreOut) { Debug.Assert(m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. // TODO: The connections should be killed instead. if (msg.HasMore) { // Find the pipe associated with the identity stored in the prefix. // If there's no such pipe just silently ignore the message, unless // mandatory is set. var identity = msg.Size == msg.Data.Length ? msg.Data : msg.CloneData(); Outpipe op; if (m_outpipes.TryGetValue(identity, out op)) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite()) { op.Active = false; m_currentOut = null; return false; } } else { throw new HostUnreachableException("In Stream.XSend"); } } m_moreOut = true; msg.Close(); msg.InitEmpty(); return true; } // Ignore the MORE flag msg.ResetFlags(MsgFlags.More); // This is the last part of the message. m_moreOut = false; // Push the message into the pipe. If there's no out pipe, just drop it. if (m_currentOut != null) { if (msg.Size == 0) { m_currentOut.Terminate(false); m_currentOut = null; return true; } bool ok = m_currentOut.Write(ref msg); if (ok) { m_currentOut.Flush(); } m_currentOut = null; } // Detach the message from the data buffer. msg.InitEmpty(); return true; }
/// <summary> /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending. /// </summary> /// <param name="msg">the message to transmit</param> /// <returns><c>true</c> if the message was sent successfully</returns> /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception> protected override bool XSend(ref Msg msg) { // If this is the first part of the message it's the ID of the // peer to send the message to. if (m_sendingState == State.RoutingId) { Debug.Assert(m_currentOut == null); // If we have malformed message (prefix with no subsequent message) // then just silently ignore it. if (msg.HasMore) { // Find the pipe associated with the routingId stored in the prefix. var routingId = msg.Size == msg.Data.Length ? msg.Data : msg.CloneData(); if (m_outpipes.TryGetValue(routingId, out Outpipe op)) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite()) { op.Active = false; m_currentOut = null; if (!op.Pipe.Active) { throw new HostUnreachableException("In Peer.XSend"); } return(false); } } else { throw new HostUnreachableException("In Peer.XSend"); } m_sendingState = State.Data; } // Detach the message from the data buffer. msg.Close(); msg.InitEmpty(); return(true); } m_sendingState = State.RoutingId; // Peer sockets do not allow multipart data (ZMQ_SNDMORE) if (msg.HasMore) { throw new InvalidException(); } // Push the message into the pipe. If there's no out pipe, just drop it. if (m_currentOut != null) { bool ok = m_currentOut.Write(ref msg); if (ok) { m_currentOut.Flush(); } m_currentOut = null; } else { msg.Close(); } // Detach the message from the data buffer. msg.InitEmpty(); return(true); }