public static bool proxy(SocketBase frontend_, SocketBase backend_, SocketBase capture_) { // The algorithm below assumes ratio of requests and replies processed // under full load to be 1:1. // TODO: The current implementation drops messages when // any of the pipes becomes full. bool success = true; int rc; long more; Msg msg; PollItem[] items = new PollItem[2]; items[0] = new PollItem (frontend_, ZMQ.ZmqPollin ); items[1] = new PollItem (backend_, ZMQ.ZmqPollin ); Selector selector; try { selector = Selector.open(); } catch (IOException e) { throw new ZError.IOException(e); } try { while (!Thread.currentThread().isInterrupted()) { // Wait while there are either requests or replies to process. rc = ZMQ.zmq_poll (selector, items, -1); if (rc < 0) return false; // Process a request. if (items [0].isReadable()) { while (true) { msg = frontend_.Recv (0); if (msg == null) { return false; } more = frontend_.getsockopt (ZMQ.ZMQ_RCVMORE); if (more < 0) return false; // Copy message to capture socket if any if (capture_ != null) { Msg ctrl = new Msg (msg); success = capture_.Send (ctrl, more > 0 ? ZMQ.ZMQ_SNDMORE: 0); if (!success) return false; } success = backend_.Send (msg, more > 0 ? ZMQ.ZMQ_SNDMORE: 0); if (!success) return false; if (more == 0) break; } } // Process a reply. if (items [1].isReadable()) { while (true) { msg = backend_.Recv (0); if (msg == null) { return false; } more = backend_.getsockopt (ZMQ.ZMQ_RCVMORE); if (more < 0) return false; // Copy message to capture socket if any if (capture_ != null) { Msg ctrl = new Msg (msg); success = capture_.Send (ctrl, more > 0 ? ZMQ.ZMQ_SNDMORE: 0); if (!success) return false; } success = frontend_.Send (msg, more > 0 ? ZMQ.ZMQ_SNDMORE: 0); if (!success) return false; if (more == 0) break; } } } } finally { try { selector.close(); } catch (Exception e) { } } return true; }
//// The proxy functionality //public static bool zmq_proxy(SocketBase frontend_, SocketBase backend_, SocketBase control_) //{ // if (frontend_ == null || backend_ == null) // { // ZError.errno = (ZError.EFAULT); // throw new ArgumentException(); // } // return Proxy.proxy( // frontend_, // backend_, // control_); //} //[Obsolete] //public static bool zmq_device(int device_, SocketBase insocket_, // SocketBase outsocket_) //{ // return Proxy.proxy(insocket_, outsocket_, null); //} public static int Poll(PollItem[] items, int timeout) { if (items == null) { ZError.ErrorNumber = (ErrorNumber.EFAULT); throw new ArgumentException(); } if (items.Length == 0) { if (timeout == 0) return 0; Thread.Sleep(timeout); return 0; } bool firstPass = true; Socket[] writeList = items.Where(p => (p.Events & PollEvents.PollOut) == PollEvents.PollOut).Select( p => p.Socket != null ? p.Socket.FD : p.FileDescriptor).ToArray(); Socket[] readList = items.Where(p => (p.Events & PollEvents.PollOut) == PollEvents.PollIn).Select( p => p.Socket != null ? p.Socket.FD : p.FileDescriptor).ToArray(); Socket[] errorList = items.Where(p => (p.Events & PollEvents.PollOut) == PollEvents.PollError).Select( p => p.Socket != null ? p.Socket.FD : p.FileDescriptor).ToArray(); Socket[] inset = new Socket[writeList.Length]; Socket[] outset = new Socket[readList.Length]; Socket[] errorset = new Socket[errorList.Length]; Dictionary<Socket, PollItem> socketsToItems = items.Select( p => new { Socket = p.Socket != null ? p.Socket.FD : p.FileDescriptor, Item = p }). ToDictionary(i => i.Socket, i => i.Item); Stopwatch stopwatch = null; while (true) { int currentTimeoutMicroSeconds; if (firstPass) { currentTimeoutMicroSeconds = 0; } else { currentTimeoutMicroSeconds = (int)((timeout - stopwatch.ElapsedMilliseconds) % 1000 * 1000); } Buffer.BlockCopy(readList, 0, inset, 0, readList.Length); Buffer.BlockCopy(writeList, 0, inset, 0, writeList.Length); Buffer.BlockCopy(errorList, 0, inset, 0, errorList.Length); try { System.Net.Sockets.Socket.Select(inset, outset, errorset, currentTimeoutMicroSeconds); } catch (SocketException ex) { // TODO: change to right error ZError.ErrorNumber = ErrorNumber.ESOCKET; return -1; } foreach (var pollItem in items) { pollItem.ResultEvent = PollEvents.None; } foreach (var socket in inset) { if (socket != null) { var item = socketsToItems[socket]; if (item.Socket != null) { PollEvents value = (PollEvents)GetSocketOption(item.Socket, ZmqSocketOptions.Events); if (value == PollEvents.PollIn) { item.ResultEvent |= PollEvents.PollIn; } } else { item.ResultEvent |= PollEvents.PollIn; } } } foreach (var socket in outset) { if (socket != null) { var item = socketsToItems[socket]; if (item.Socket != null) { PollEvents value = (PollEvents)GetSocketOption(item.Socket, ZmqSocketOptions.Events); if (value == PollEvents.PollOut) { item.ResultEvent |= PollEvents.PollOut; } } else { item.ResultEvent |= PollEvents.PollOut; } } } foreach (var socket in errorList) { if (socket != null) { var item = socketsToItems[socket]; if (item.Socket == null) { item.ResultEvent |= PollEvents.PollError; } } } if (timeout == 0) { break; } if (items.Any(i => i.ResultEvent != PollEvents.None)) { break; } if (timeout < 0) { if (firstPass) { firstPass = false; } continue; } if (firstPass) { stopwatch = Stopwatch.StartNew(); firstPass = false; continue; } if (stopwatch.ElapsedMilliseconds > timeout) { break; } } return items.Where(i => i.ResultEvent != PollEvents.None).Count(); }