protected override void XAttachPipe(Pipe pipe, bool icanhasall) { Debug.Assert(pipe != null); // ZMQ_PAIR socket can only be connected to a single peer. // The socket rejects any further connection requests. if (m_pipe == null) m_pipe = pipe; else pipe.Terminate (false); }
protected virtual void XHiccuped(Pipe pipe) { throw new NotSupportedException("Must override"); }
public Outpipe(Pipe pipe, bool active) { Pipe = pipe; Active = active; }
protected override void XWriteActivated(Pipe pipe) { foreach (var it in m_outpipes) { if (it.Value.Pipe == pipe) { Debug.Assert(!it.Value.Active); it.Value.Active = true; break; } } Debug.Assert(false); }
protected override bool XSend(Msg msg, SendRecieveOptions flags) { // 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. Blob identity = new Blob(msg.Data); Outpipe op = m_outpipes[identity]; if (op != null) { m_currentOut = op.Pipe; if (!m_currentOut.CheckWrite ()) { op.Active = false; m_currentOut = null; } } else if (m_mandatory) { m_moreOut = false; ZError.ErrorNumber = (ErrorNumber.EHOSTUNREACH); return false; } } return true; } // 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) { bool ok = m_currentOut.Write (msg); if (!ok) m_currentOut = null; else if (!m_moreOut) { m_currentOut.Flush (); m_currentOut = null; } } else { } // Detach the message from the data buffer. return true; }
protected override void XReadActivated(Pipe pipe) { if (!m_anonymousPipes.Contains(pipe)) m_fq.Activated (pipe); else { bool identityOk = IdentifyPeer (pipe); if (identityOk) { m_anonymousPipes.Remove(pipe); m_fq.Attach (pipe); } } }
protected override void XAttachPipe(Pipe pipe, bool icanhasall) { Debug.Assert(pipe != null); bool identityOk = IdentifyPeer (pipe); if (identityOk) m_fq.Attach (pipe); else m_anonymousPipes.Add (pipe); }
protected override void XReadActivated(Pipe pipe) { // There's just one pipe. No lists of active and inactive pipes. // There's nothing to do here. }
public void Terminated(Pipe pipe) { // Notify the specific socket type about the pipe termination. XTerminated(pipe); // Remove the pipe from the list of attached pipes and confirm its // termination if we are already shutting down. m_pipes.Remove(pipe); if (IsTerminating) UnregisterTermAck(); }
public void ReadActivated(Pipe pipe) { XReadActivated(pipe); }
public void Hiccuped(Pipe pipe) { if (m_options.DelayAttachOnConnect) pipe.Terminate(false); else // Notify derived sockets of the hiccup XHiccuped(pipe); }
private void AttachPipe(Pipe pipe, bool icanhasall) { // First, register the pipe so that we can terminate it later on. pipe.SetEventSink(this); m_pipes.Add(pipe); // Let the derived socket type know about new pipe. XAttachPipe(pipe, icanhasall); // If the socket is already being closed, ask any new pipes to terminate // straight away. if (IsTerminating) { RegisterTermAcks(1); pipe.Terminate(false); } }
// Register the pipe with this socket. private void AttachPipe(Pipe pipe) { AttachPipe(pipe, false); }
protected virtual void XWriteActivated(Pipe pipe) { throw new NotSupportedException("Must Override"); }
protected abstract void XTerminated(Pipe pipe);
protected override void XTerminated(Pipe pipe) { if (pipe == m_pipe) m_pipe = null; }
public void WriteActivated(Pipe pipe) { XWriteActivated(pipe); }
public void Terminated(Pipe pipe) { int index = m_pipes.IndexOf (pipe); // If we are in the middle of multipart message and current pipe // have disconnected, we have to drop the remainder of the message. if (index == m_current && m_more) m_dropping = true; // Remove the pipe from the list; adjust number of active pipes // accordingly. if (index < m_active) { m_active--; Utils.Swap (m_pipes, index, m_active); if (m_current == m_active) m_current = 0; } m_pipes.Remove (pipe); }
// Rollback any message parts that were sent but not yet flushed. protected void Rollback() { if (m_currentOut != null) { m_currentOut.Rollback (); m_currentOut = null; m_moreOut = false; } }
public void Activated(Pipe pipe) { // Move the pipe to the list of active pipes. Utils.Swap (m_pipes, m_pipes.IndexOf (pipe), m_active); m_active++; }
protected override bool XHasIn() { // If we are in the middle of reading the messages, there are // definitely more parts available. if (m_moreIn) return true; // We may already have a message pre-fetched. if (m_prefetched) return true; // Try to read the next message. // The message, if read, is kept in the pre-fetch buffer. Pipe[] pipe = new Pipe[1]; m_prefetchedMsg = m_fq.RecvPipe (pipe); // It's possible that we receive peer's identity. That happens // after reconnection. The current implementation assumes that // the peer always uses the same identity. // TODO: handle the situation when the peer changes its identity. while (m_prefetchedMsg != null && m_prefetchedMsg.IsIdentity ) m_prefetchedMsg = m_fq.RecvPipe (pipe); if (m_prefetchedMsg == null) return false; Debug.Assert(pipe[0] != null); Blob identity = pipe[0].Identity ; m_prefetchedId = new Msg(identity.Data); m_prefetchedId.SetFlags(MsgFlags.More); m_prefetched = true; m_identitySent = false; return true; }
public void Attach(Pipe pipe) { m_pipes.Add (pipe); Activated (pipe); }
protected override Msg XRecv(SendRecieveOptions flags) { Msg msg = null; if (m_prefetched) { if (!m_identitySent) { msg = m_prefetchedId; m_prefetchedId = null; m_identitySent = true; } else { msg = m_prefetchedMsg; m_prefetchedMsg = null; m_prefetched = false; } m_moreIn = msg.HasMore; return msg; } Pipe[] pipe = new Pipe[1]; msg = m_fq.RecvPipe (pipe); // It's possible that we receive peer's identity. That happens // after reconnection. The current implementation assumes that // the peer always uses the same identity. // TODO: handle the situation when the peer changes its identity. while (msg != null && msg.IsIdentity ) msg = m_fq.RecvPipe (pipe); if (msg == null) return null; Debug.Assert(pipe[0] != null); // If we are in the middle of reading a message, just return the next part. if (m_moreIn) m_moreIn = msg.HasMore; else { // We are at the beginning of a message. // Keep the message part we have in the prefetch buffer // and return the ID of the peer instead. m_prefetchedMsg = msg; m_prefetched = true; Blob identity = pipe[0].Identity; msg = new Msg(identity.Data); msg.SetFlags(MsgFlags.More); m_identitySent = true; } return msg; }
protected override void XAttachPipe(Pipe pipe, bool icanhasall) { Debug.Assert(pipe != null); lb.Attach (pipe); }
protected override void XTerminated(Pipe pipe) { if (!m_anonymousPipes.Remove(pipe)) { Outpipe old; m_outpipes.TryGetValue(pipe.Identity, out old); m_outpipes.Remove(pipe.Identity); Debug.Assert(old != null); m_fq.Terminated (pipe); if (pipe == m_currentOut) m_currentOut = null; } }
protected override void XTerminated(Pipe pipe) { lb.Terminated (pipe); }
private bool IdentifyPeer(Pipe pipe) { Blob identity; Msg msg = pipe.Read (); if (msg == null) return false; if (msg.Size == 0) { // Fall back on the auto-generation byte[] buf = new byte[5]; buf[0] = 0; byte[] result = BitConverter.GetBytes(m_nextPeerId++); //if (BitConverter.IsLittleEndian) //{ // Array.Reverse(result); //} Buffer.BlockCopy(result, 0, buf, 1, 4); identity = new Blob(buf); } else { identity = new Blob(msg.Data); // Ignore peers with duplicate ID. if (m_outpipes.ContainsKey(identity)) return false; } pipe.Identity = identity; // Add the record into output pipes lookup table Outpipe outpipe = new Outpipe(pipe, true); m_outpipes.Add (identity, outpipe); return true; }
protected override void XWriteActivated(Pipe pipe) { lb.Activated (pipe); }
public Router(Ctx parent, int tid, int sid) : base(parent, tid, sid) { m_prefetched = false; m_identitySent = false; m_moreIn = false; m_currentOut = null; m_moreOut = false; m_nextPeerId = Utils.GenerateRandom (); m_mandatory = false; m_options.SocketType = ZmqSocketType.Router; m_fq = new FQ(); m_prefetchedId = new Msg(); m_prefetchedMsg = new Msg(); m_anonymousPipes = new HashSet<Pipe>(); m_outpipes = new Dictionary<Blob, Outpipe>(); // TODO: Uncomment the following line when ROUTER will become true ROUTER // rather than generic router socket. // If peer disconnect there's noone to send reply to anyway. We can drop // all the outstanding requests from that peer. // options.delay_on_disconnect = false; m_options.RecvIdentity = true; }
// Concrete algorithms for the x- methods are to be defined by // individual socket types. protected abstract void XAttachPipe(Pipe pipe, bool icanhasall);