diff options
Diffstat (limited to 'src')
164 files changed, 0 insertions, 29546 deletions
diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index fd268a7..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,196 +0,0 @@ -lib_LTLIBRARIES = libzmq.la - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libzmq.pc - -include_HEADERS = ../include/zmq.h ../include/zmq_utils.h - -libzmq_la_SOURCES = \ - address.hpp \ - array.hpp \ - atomic_counter.hpp \ - atomic_ptr.hpp \ - blob.hpp \ - clock.hpp \ - command.hpp \ - config.hpp \ - ctx.hpp \ - curve_client.hpp \ - curve_server.hpp \ - decoder.hpp \ - devpoll.hpp \ - dist.hpp \ - encoder.hpp \ - epoll.hpp \ - err.hpp \ - fd.hpp \ - fq.hpp \ - i_encoder.hpp \ - i_decoder.hpp \ - i_engine.hpp \ - i_poll_events.hpp \ - io_object.hpp \ - io_thread.hpp \ - ip.hpp \ - ipc_address.hpp \ - ipc_connecter.hpp \ - ipc_listener.hpp \ - i_engine.hpp \ - i_poll_events.hpp \ - kqueue.hpp \ - lb.hpp \ - likely.hpp \ - mailbox.hpp \ - mechanism.hpp \ - msg.hpp \ - mtrie.hpp \ - mutex.hpp \ - null_mechanism.hpp \ - object.hpp \ - options.hpp \ - own.hpp \ - pgm_receiver.hpp \ - pgm_sender.hpp \ - pgm_socket.hpp \ - pipe.hpp \ - plain_mechanism.hpp \ - platform.hpp \ - poll.hpp \ - poller.hpp \ - poller_base.hpp \ - pair.hpp \ - proxy.hpp \ - pub.hpp \ - pull.hpp \ - push.hpp \ - random.hpp \ - reaper.hpp \ - rep.hpp \ - req.hpp \ - select.hpp \ - session_base.hpp \ - signaler.hpp \ - socket_base.hpp \ - stdint.hpp \ - stream.hpp \ - stream_engine.hpp \ - sub.hpp \ - tcp.hpp \ - tcp_address.hpp \ - tcp_connecter.hpp \ - tcp_listener.hpp \ - thread.hpp \ - trie.hpp \ - windows.hpp \ - wire.hpp \ - xpub.hpp \ - router.hpp \ - dealer.hpp \ - xsub.hpp \ - ypipe.hpp \ - ypipe_base.hpp \ - yqueue.hpp \ - address.cpp \ - clock.cpp \ - ctx.cpp \ - curve_client.cpp \ - curve_server.cpp \ - devpoll.cpp \ - dist.cpp \ - epoll.cpp \ - err.cpp \ - fq.cpp \ - io_object.cpp \ - io_thread.cpp \ - ip.cpp \ - ipc_address.cpp \ - ipc_connecter.cpp \ - ipc_listener.cpp \ - kqueue.cpp \ - lb.cpp \ - mailbox.cpp \ - mechanism.cpp \ - msg.cpp \ - mtrie.cpp \ - null_mechanism.cpp \ - object.cpp \ - options.cpp \ - own.cpp \ - pair.cpp \ - pgm_receiver.cpp \ - pgm_sender.cpp \ - pgm_socket.cpp \ - pipe.cpp \ - plain_mechanism.cpp \ - poll.cpp \ - poller_base.cpp \ - pull.cpp \ - push.cpp \ - proxy.cpp \ - reaper.cpp \ - pub.cpp \ - random.cpp \ - rep.cpp \ - req.cpp \ - select.cpp \ - session_base.cpp \ - signaler.cpp \ - socket_base.cpp \ - stream.cpp \ - stream_engine.cpp \ - sub.cpp \ - tcp.cpp \ - tcp_address.cpp \ - tcp_connecter.cpp \ - tcp_listener.cpp \ - thread.cpp \ - trie.cpp \ - xpub.cpp \ - router.cpp \ - dealer.cpp \ - v1_decoder.cpp \ - v1_encoder.cpp \ - v1_decoder.hpp \ - v1_encoder.hpp \ - v2_decoder.cpp \ - v2_decoder.hpp \ - v2_encoder.cpp \ - v2_encoder.hpp \ - v2_protocol.hpp \ - xsub.cpp \ - zmq.cpp \ - zmq_utils.cpp \ - raw_decoder.hpp \ - raw_decoder.cpp \ - raw_encoder.hpp \ - raw_encoder.cpp \ - ypipe_conflate.hpp \ - dbuffer.hpp - -if ON_MINGW -libzmq_la_LDFLAGS = -no-undefined -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -else -if ON_ANDROID -libzmq_la_LDFLAGS = -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -else -if ON_LINUX -libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl,--version-script=$(srcdir)/libzmq.vers -else -libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl -endif -endif -endif - -EXTRA_DIST = libzmq.vers - -libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ - -if BUILD_PGM -libzmq_la_CPPFLAGS = -I$(top_srcdir)/@pgm_srcdir@/include/ -libzmq_la_LIBADD = $(top_srcdir)/@pgm_srcdir@/libpgm_noinst.la -endif - -dist-hook: - -rm $(distdir)/platform.hpp - - diff --git a/src/Makefile.in b/src/Makefile.in deleted file mode 100644 index 38898e1..0000000 --- a/src/Makefile.in +++ /dev/null @@ -1,1393 +0,0 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src -DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/libzmq.pc.in \ - $(srcdir)/platform.hpp.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ - $(top_srcdir)/config/ltoptions.m4 \ - $(top_srcdir)/config/ltsugar.m4 \ - $(top_srcdir)/config/ltversion.m4 \ - $(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = platform.hpp -CONFIG_CLEAN_FILES = libzmq.pc -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ - "$(DESTDIR)$(includedir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -@BUILD_PGM_TRUE@libzmq_la_DEPENDENCIES = \ -@BUILD_PGM_TRUE@ $(top_srcdir)/@pgm_srcdir@/libpgm_noinst.la -am_libzmq_la_OBJECTS = libzmq_la-address.lo libzmq_la-clock.lo \ - libzmq_la-ctx.lo libzmq_la-curve_client.lo \ - libzmq_la-curve_server.lo libzmq_la-devpoll.lo \ - libzmq_la-dist.lo libzmq_la-epoll.lo libzmq_la-err.lo \ - libzmq_la-fq.lo libzmq_la-io_object.lo libzmq_la-io_thread.lo \ - libzmq_la-ip.lo libzmq_la-ipc_address.lo \ - libzmq_la-ipc_connecter.lo libzmq_la-ipc_listener.lo \ - libzmq_la-kqueue.lo libzmq_la-lb.lo libzmq_la-mailbox.lo \ - libzmq_la-mechanism.lo libzmq_la-msg.lo libzmq_la-mtrie.lo \ - libzmq_la-null_mechanism.lo libzmq_la-object.lo \ - libzmq_la-options.lo libzmq_la-own.lo libzmq_la-pair.lo \ - libzmq_la-pgm_receiver.lo libzmq_la-pgm_sender.lo \ - libzmq_la-pgm_socket.lo libzmq_la-pipe.lo \ - libzmq_la-plain_mechanism.lo libzmq_la-poll.lo \ - libzmq_la-poller_base.lo libzmq_la-pull.lo libzmq_la-push.lo \ - libzmq_la-proxy.lo libzmq_la-reaper.lo libzmq_la-pub.lo \ - libzmq_la-random.lo libzmq_la-rep.lo libzmq_la-req.lo \ - libzmq_la-select.lo libzmq_la-session_base.lo \ - libzmq_la-signaler.lo libzmq_la-socket_base.lo \ - libzmq_la-stream.lo libzmq_la-stream_engine.lo \ - libzmq_la-sub.lo libzmq_la-tcp.lo libzmq_la-tcp_address.lo \ - libzmq_la-tcp_connecter.lo libzmq_la-tcp_listener.lo \ - libzmq_la-thread.lo libzmq_la-trie.lo libzmq_la-xpub.lo \ - libzmq_la-router.lo libzmq_la-dealer.lo \ - libzmq_la-v1_decoder.lo libzmq_la-v1_encoder.lo \ - libzmq_la-v2_decoder.lo libzmq_la-v2_encoder.lo \ - libzmq_la-xsub.lo libzmq_la-zmq.lo libzmq_la-zmq_utils.lo \ - libzmq_la-raw_decoder.lo libzmq_la-raw_encoder.lo -libzmq_la_OBJECTS = $(am_libzmq_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -libzmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libzmq_la_CXXFLAGS) \ - $(CXXFLAGS) $(libzmq_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(libzmq_la_SOURCES) -DIST_SOURCES = $(libzmq_la_SOURCES) -DATA = $(pkgconfig_DATA) -HEADERS = $(include_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AS = @AS@ -ASCIIDOC = @ASCIIDOC@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBZMQ_EXTRA_CFLAGS = @LIBZMQ_EXTRA_CFLAGS@ -LIBZMQ_EXTRA_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ -LIBZMQ_EXTRA_LDFLAGS = @LIBZMQ_EXTRA_LDFLAGS@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LTVER = @LTVER@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -OpenPGM_CFLAGS = @OpenPGM_CFLAGS@ -OpenPGM_LIBS = @OpenPGM_LIBS@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -XMLTO = @XMLTO@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -libzmq_have_asciidoc = @libzmq_have_asciidoc@ -libzmq_have_xmlto = @libzmq_have_xmlto@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pgm_basename = @pgm_basename@ -pgm_srcdir = @pgm_srcdir@ -pgm_subdir = @pgm_subdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -lib_LTLIBRARIES = libzmq.la -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libzmq.pc -include_HEADERS = ../include/zmq.h ../include/zmq_utils.h -libzmq_la_SOURCES = \ - address.hpp \ - array.hpp \ - atomic_counter.hpp \ - atomic_ptr.hpp \ - blob.hpp \ - clock.hpp \ - command.hpp \ - config.hpp \ - ctx.hpp \ - curve_client.hpp \ - curve_server.hpp \ - decoder.hpp \ - devpoll.hpp \ - dist.hpp \ - encoder.hpp \ - epoll.hpp \ - err.hpp \ - fd.hpp \ - fq.hpp \ - i_encoder.hpp \ - i_decoder.hpp \ - i_engine.hpp \ - i_poll_events.hpp \ - io_object.hpp \ - io_thread.hpp \ - ip.hpp \ - ipc_address.hpp \ - ipc_connecter.hpp \ - ipc_listener.hpp \ - i_engine.hpp \ - i_poll_events.hpp \ - kqueue.hpp \ - lb.hpp \ - likely.hpp \ - mailbox.hpp \ - mechanism.hpp \ - msg.hpp \ - mtrie.hpp \ - mutex.hpp \ - null_mechanism.hpp \ - object.hpp \ - options.hpp \ - own.hpp \ - pgm_receiver.hpp \ - pgm_sender.hpp \ - pgm_socket.hpp \ - pipe.hpp \ - plain_mechanism.hpp \ - platform.hpp \ - poll.hpp \ - poller.hpp \ - poller_base.hpp \ - pair.hpp \ - proxy.hpp \ - pub.hpp \ - pull.hpp \ - push.hpp \ - random.hpp \ - reaper.hpp \ - rep.hpp \ - req.hpp \ - select.hpp \ - session_base.hpp \ - signaler.hpp \ - socket_base.hpp \ - stdint.hpp \ - stream.hpp \ - stream_engine.hpp \ - sub.hpp \ - tcp.hpp \ - tcp_address.hpp \ - tcp_connecter.hpp \ - tcp_listener.hpp \ - thread.hpp \ - trie.hpp \ - windows.hpp \ - wire.hpp \ - xpub.hpp \ - router.hpp \ - dealer.hpp \ - xsub.hpp \ - ypipe.hpp \ - ypipe_base.hpp \ - yqueue.hpp \ - address.cpp \ - clock.cpp \ - ctx.cpp \ - curve_client.cpp \ - curve_server.cpp \ - devpoll.cpp \ - dist.cpp \ - epoll.cpp \ - err.cpp \ - fq.cpp \ - io_object.cpp \ - io_thread.cpp \ - ip.cpp \ - ipc_address.cpp \ - ipc_connecter.cpp \ - ipc_listener.cpp \ - kqueue.cpp \ - lb.cpp \ - mailbox.cpp \ - mechanism.cpp \ - msg.cpp \ - mtrie.cpp \ - null_mechanism.cpp \ - object.cpp \ - options.cpp \ - own.cpp \ - pair.cpp \ - pgm_receiver.cpp \ - pgm_sender.cpp \ - pgm_socket.cpp \ - pipe.cpp \ - plain_mechanism.cpp \ - poll.cpp \ - poller_base.cpp \ - pull.cpp \ - push.cpp \ - proxy.cpp \ - reaper.cpp \ - pub.cpp \ - random.cpp \ - rep.cpp \ - req.cpp \ - select.cpp \ - session_base.cpp \ - signaler.cpp \ - socket_base.cpp \ - stream.cpp \ - stream_engine.cpp \ - sub.cpp \ - tcp.cpp \ - tcp_address.cpp \ - tcp_connecter.cpp \ - tcp_listener.cpp \ - thread.cpp \ - trie.cpp \ - xpub.cpp \ - router.cpp \ - dealer.cpp \ - v1_decoder.cpp \ - v1_encoder.cpp \ - v1_decoder.hpp \ - v1_encoder.hpp \ - v2_decoder.cpp \ - v2_decoder.hpp \ - v2_encoder.cpp \ - v2_encoder.hpp \ - v2_protocol.hpp \ - xsub.cpp \ - zmq.cpp \ - zmq_utils.cpp \ - raw_decoder.hpp \ - raw_decoder.cpp \ - raw_encoder.hpp \ - raw_encoder.cpp \ - ypipe_conflate.hpp \ - dbuffer.hpp - -@ON_ANDROID_FALSE@@ON_LINUX_FALSE@@ON_MINGW_FALSE@libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl -@ON_ANDROID_FALSE@@ON_LINUX_TRUE@@ON_MINGW_FALSE@libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl,--version-script=$(srcdir)/libzmq.vers -@ON_ANDROID_TRUE@@ON_MINGW_FALSE@libzmq_la_LDFLAGS = -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -@ON_MINGW_TRUE@libzmq_la_LDFLAGS = -no-undefined -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -EXTRA_DIST = libzmq.vers -libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ -@BUILD_PGM_TRUE@libzmq_la_CPPFLAGS = -I$(top_srcdir)/@pgm_srcdir@/include/ -@BUILD_PGM_TRUE@libzmq_la_LIBADD = $(top_srcdir)/@pgm_srcdir@/libpgm_noinst.la -all: platform.hpp - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .cpp .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -platform.hpp: stamp-h1 - @if test ! -f $@; then rm -f stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi - -stamp-h1: $(srcdir)/platform.hpp.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status src/platform.hpp -$(srcdir)/platform.hpp.in: $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f platform.hpp stamp-h1 -libzmq.pc: $(top_builddir)/config.status $(srcdir)/libzmq.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libzmq.la: $(libzmq_la_OBJECTS) $(libzmq_la_DEPENDENCIES) $(EXTRA_libzmq_la_DEPENDENCIES) - $(AM_V_CXXLD)$(libzmq_la_LINK) -rpath $(libdir) $(libzmq_la_OBJECTS) $(libzmq_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-address.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-clock.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-ctx.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-curve_client.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-curve_server.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-dealer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-devpoll.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-dist.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-epoll.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-err.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-fq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-io_object.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-io_thread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-ip.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-ipc_address.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-ipc_connecter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-ipc_listener.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-kqueue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-lb.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-mailbox.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-mechanism.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-msg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-mtrie.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-null_mechanism.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-object.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-options.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-own.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pair.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pgm_receiver.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pgm_sender.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pgm_socket.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pipe.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-plain_mechanism.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-poll.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-poller_base.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-proxy.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pub.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-pull.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-push.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-random.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-raw_decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-raw_encoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-reaper.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-rep.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-req.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-router.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-select.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-session_base.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-signaler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-socket_base.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-stream_engine.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-sub.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-tcp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-tcp_address.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-tcp_connecter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-tcp_listener.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-thread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-trie.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-v1_decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-v1_encoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-v2_decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-v2_encoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-xpub.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-xsub.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-zmq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libzmq_la-zmq_utils.Plo@am__quote@ - -.cpp.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cpp.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cpp.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -libzmq_la-address.lo: address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-address.lo -MD -MP -MF $(DEPDIR)/libzmq_la-address.Tpo -c -o libzmq_la-address.lo `test -f 'address.cpp' || echo '$(srcdir)/'`address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-address.Tpo $(DEPDIR)/libzmq_la-address.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='address.cpp' object='libzmq_la-address.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-address.lo `test -f 'address.cpp' || echo '$(srcdir)/'`address.cpp - -libzmq_la-clock.lo: clock.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-clock.lo -MD -MP -MF $(DEPDIR)/libzmq_la-clock.Tpo -c -o libzmq_la-clock.lo `test -f 'clock.cpp' || echo '$(srcdir)/'`clock.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-clock.Tpo $(DEPDIR)/libzmq_la-clock.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='clock.cpp' object='libzmq_la-clock.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-clock.lo `test -f 'clock.cpp' || echo '$(srcdir)/'`clock.cpp - -libzmq_la-ctx.lo: ctx.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-ctx.lo -MD -MP -MF $(DEPDIR)/libzmq_la-ctx.Tpo -c -o libzmq_la-ctx.lo `test -f 'ctx.cpp' || echo '$(srcdir)/'`ctx.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-ctx.Tpo $(DEPDIR)/libzmq_la-ctx.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ctx.cpp' object='libzmq_la-ctx.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-ctx.lo `test -f 'ctx.cpp' || echo '$(srcdir)/'`ctx.cpp - -libzmq_la-curve_client.lo: curve_client.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-curve_client.lo -MD -MP -MF $(DEPDIR)/libzmq_la-curve_client.Tpo -c -o libzmq_la-curve_client.lo `test -f 'curve_client.cpp' || echo '$(srcdir)/'`curve_client.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-curve_client.Tpo $(DEPDIR)/libzmq_la-curve_client.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='curve_client.cpp' object='libzmq_la-curve_client.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-curve_client.lo `test -f 'curve_client.cpp' || echo '$(srcdir)/'`curve_client.cpp - -libzmq_la-curve_server.lo: curve_server.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-curve_server.lo -MD -MP -MF $(DEPDIR)/libzmq_la-curve_server.Tpo -c -o libzmq_la-curve_server.lo `test -f 'curve_server.cpp' || echo '$(srcdir)/'`curve_server.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-curve_server.Tpo $(DEPDIR)/libzmq_la-curve_server.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='curve_server.cpp' object='libzmq_la-curve_server.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-curve_server.lo `test -f 'curve_server.cpp' || echo '$(srcdir)/'`curve_server.cpp - -libzmq_la-devpoll.lo: devpoll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-devpoll.lo -MD -MP -MF $(DEPDIR)/libzmq_la-devpoll.Tpo -c -o libzmq_la-devpoll.lo `test -f 'devpoll.cpp' || echo '$(srcdir)/'`devpoll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-devpoll.Tpo $(DEPDIR)/libzmq_la-devpoll.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='devpoll.cpp' object='libzmq_la-devpoll.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-devpoll.lo `test -f 'devpoll.cpp' || echo '$(srcdir)/'`devpoll.cpp - -libzmq_la-dist.lo: dist.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-dist.lo -MD -MP -MF $(DEPDIR)/libzmq_la-dist.Tpo -c -o libzmq_la-dist.lo `test -f 'dist.cpp' || echo '$(srcdir)/'`dist.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-dist.Tpo $(DEPDIR)/libzmq_la-dist.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dist.cpp' object='libzmq_la-dist.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-dist.lo `test -f 'dist.cpp' || echo '$(srcdir)/'`dist.cpp - -libzmq_la-epoll.lo: epoll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-epoll.lo -MD -MP -MF $(DEPDIR)/libzmq_la-epoll.Tpo -c -o libzmq_la-epoll.lo `test -f 'epoll.cpp' || echo '$(srcdir)/'`epoll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-epoll.Tpo $(DEPDIR)/libzmq_la-epoll.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='epoll.cpp' object='libzmq_la-epoll.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-epoll.lo `test -f 'epoll.cpp' || echo '$(srcdir)/'`epoll.cpp - -libzmq_la-err.lo: err.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-err.lo -MD -MP -MF $(DEPDIR)/libzmq_la-err.Tpo -c -o libzmq_la-err.lo `test -f 'err.cpp' || echo '$(srcdir)/'`err.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-err.Tpo $(DEPDIR)/libzmq_la-err.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='err.cpp' object='libzmq_la-err.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-err.lo `test -f 'err.cpp' || echo '$(srcdir)/'`err.cpp - -libzmq_la-fq.lo: fq.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-fq.lo -MD -MP -MF $(DEPDIR)/libzmq_la-fq.Tpo -c -o libzmq_la-fq.lo `test -f 'fq.cpp' || echo '$(srcdir)/'`fq.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-fq.Tpo $(DEPDIR)/libzmq_la-fq.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='fq.cpp' object='libzmq_la-fq.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-fq.lo `test -f 'fq.cpp' || echo '$(srcdir)/'`fq.cpp - -libzmq_la-io_object.lo: io_object.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-io_object.lo -MD -MP -MF $(DEPDIR)/libzmq_la-io_object.Tpo -c -o libzmq_la-io_object.lo `test -f 'io_object.cpp' || echo '$(srcdir)/'`io_object.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-io_object.Tpo $(DEPDIR)/libzmq_la-io_object.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='io_object.cpp' object='libzmq_la-io_object.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-io_object.lo `test -f 'io_object.cpp' || echo '$(srcdir)/'`io_object.cpp - -libzmq_la-io_thread.lo: io_thread.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-io_thread.lo -MD -MP -MF $(DEPDIR)/libzmq_la-io_thread.Tpo -c -o libzmq_la-io_thread.lo `test -f 'io_thread.cpp' || echo '$(srcdir)/'`io_thread.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-io_thread.Tpo $(DEPDIR)/libzmq_la-io_thread.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='io_thread.cpp' object='libzmq_la-io_thread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-io_thread.lo `test -f 'io_thread.cpp' || echo '$(srcdir)/'`io_thread.cpp - -libzmq_la-ip.lo: ip.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-ip.lo -MD -MP -MF $(DEPDIR)/libzmq_la-ip.Tpo -c -o libzmq_la-ip.lo `test -f 'ip.cpp' || echo '$(srcdir)/'`ip.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-ip.Tpo $(DEPDIR)/libzmq_la-ip.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ip.cpp' object='libzmq_la-ip.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-ip.lo `test -f 'ip.cpp' || echo '$(srcdir)/'`ip.cpp - -libzmq_la-ipc_address.lo: ipc_address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-ipc_address.lo -MD -MP -MF $(DEPDIR)/libzmq_la-ipc_address.Tpo -c -o libzmq_la-ipc_address.lo `test -f 'ipc_address.cpp' || echo '$(srcdir)/'`ipc_address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-ipc_address.Tpo $(DEPDIR)/libzmq_la-ipc_address.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ipc_address.cpp' object='libzmq_la-ipc_address.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-ipc_address.lo `test -f 'ipc_address.cpp' || echo '$(srcdir)/'`ipc_address.cpp - -libzmq_la-ipc_connecter.lo: ipc_connecter.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-ipc_connecter.lo -MD -MP -MF $(DEPDIR)/libzmq_la-ipc_connecter.Tpo -c -o libzmq_la-ipc_connecter.lo `test -f 'ipc_connecter.cpp' || echo '$(srcdir)/'`ipc_connecter.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-ipc_connecter.Tpo $(DEPDIR)/libzmq_la-ipc_connecter.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ipc_connecter.cpp' object='libzmq_la-ipc_connecter.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-ipc_connecter.lo `test -f 'ipc_connecter.cpp' || echo '$(srcdir)/'`ipc_connecter.cpp - -libzmq_la-ipc_listener.lo: ipc_listener.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-ipc_listener.lo -MD -MP -MF $(DEPDIR)/libzmq_la-ipc_listener.Tpo -c -o libzmq_la-ipc_listener.lo `test -f 'ipc_listener.cpp' || echo '$(srcdir)/'`ipc_listener.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-ipc_listener.Tpo $(DEPDIR)/libzmq_la-ipc_listener.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ipc_listener.cpp' object='libzmq_la-ipc_listener.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-ipc_listener.lo `test -f 'ipc_listener.cpp' || echo '$(srcdir)/'`ipc_listener.cpp - -libzmq_la-kqueue.lo: kqueue.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-kqueue.lo -MD -MP -MF $(DEPDIR)/libzmq_la-kqueue.Tpo -c -o libzmq_la-kqueue.lo `test -f 'kqueue.cpp' || echo '$(srcdir)/'`kqueue.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-kqueue.Tpo $(DEPDIR)/libzmq_la-kqueue.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='kqueue.cpp' object='libzmq_la-kqueue.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-kqueue.lo `test -f 'kqueue.cpp' || echo '$(srcdir)/'`kqueue.cpp - -libzmq_la-lb.lo: lb.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-lb.lo -MD -MP -MF $(DEPDIR)/libzmq_la-lb.Tpo -c -o libzmq_la-lb.lo `test -f 'lb.cpp' || echo '$(srcdir)/'`lb.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-lb.Tpo $(DEPDIR)/libzmq_la-lb.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lb.cpp' object='libzmq_la-lb.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-lb.lo `test -f 'lb.cpp' || echo '$(srcdir)/'`lb.cpp - -libzmq_la-mailbox.lo: mailbox.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-mailbox.lo -MD -MP -MF $(DEPDIR)/libzmq_la-mailbox.Tpo -c -o libzmq_la-mailbox.lo `test -f 'mailbox.cpp' || echo '$(srcdir)/'`mailbox.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-mailbox.Tpo $(DEPDIR)/libzmq_la-mailbox.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mailbox.cpp' object='libzmq_la-mailbox.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-mailbox.lo `test -f 'mailbox.cpp' || echo '$(srcdir)/'`mailbox.cpp - -libzmq_la-mechanism.lo: mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-mechanism.lo -MD -MP -MF $(DEPDIR)/libzmq_la-mechanism.Tpo -c -o libzmq_la-mechanism.lo `test -f 'mechanism.cpp' || echo '$(srcdir)/'`mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-mechanism.Tpo $(DEPDIR)/libzmq_la-mechanism.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mechanism.cpp' object='libzmq_la-mechanism.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-mechanism.lo `test -f 'mechanism.cpp' || echo '$(srcdir)/'`mechanism.cpp - -libzmq_la-msg.lo: msg.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-msg.lo -MD -MP -MF $(DEPDIR)/libzmq_la-msg.Tpo -c -o libzmq_la-msg.lo `test -f 'msg.cpp' || echo '$(srcdir)/'`msg.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-msg.Tpo $(DEPDIR)/libzmq_la-msg.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='msg.cpp' object='libzmq_la-msg.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-msg.lo `test -f 'msg.cpp' || echo '$(srcdir)/'`msg.cpp - -libzmq_la-mtrie.lo: mtrie.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-mtrie.lo -MD -MP -MF $(DEPDIR)/libzmq_la-mtrie.Tpo -c -o libzmq_la-mtrie.lo `test -f 'mtrie.cpp' || echo '$(srcdir)/'`mtrie.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-mtrie.Tpo $(DEPDIR)/libzmq_la-mtrie.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mtrie.cpp' object='libzmq_la-mtrie.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-mtrie.lo `test -f 'mtrie.cpp' || echo '$(srcdir)/'`mtrie.cpp - -libzmq_la-null_mechanism.lo: null_mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-null_mechanism.lo -MD -MP -MF $(DEPDIR)/libzmq_la-null_mechanism.Tpo -c -o libzmq_la-null_mechanism.lo `test -f 'null_mechanism.cpp' || echo '$(srcdir)/'`null_mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-null_mechanism.Tpo $(DEPDIR)/libzmq_la-null_mechanism.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='null_mechanism.cpp' object='libzmq_la-null_mechanism.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-null_mechanism.lo `test -f 'null_mechanism.cpp' || echo '$(srcdir)/'`null_mechanism.cpp - -libzmq_la-object.lo: object.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-object.lo -MD -MP -MF $(DEPDIR)/libzmq_la-object.Tpo -c -o libzmq_la-object.lo `test -f 'object.cpp' || echo '$(srcdir)/'`object.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-object.Tpo $(DEPDIR)/libzmq_la-object.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='object.cpp' object='libzmq_la-object.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-object.lo `test -f 'object.cpp' || echo '$(srcdir)/'`object.cpp - -libzmq_la-options.lo: options.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-options.lo -MD -MP -MF $(DEPDIR)/libzmq_la-options.Tpo -c -o libzmq_la-options.lo `test -f 'options.cpp' || echo '$(srcdir)/'`options.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-options.Tpo $(DEPDIR)/libzmq_la-options.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='options.cpp' object='libzmq_la-options.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-options.lo `test -f 'options.cpp' || echo '$(srcdir)/'`options.cpp - -libzmq_la-own.lo: own.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-own.lo -MD -MP -MF $(DEPDIR)/libzmq_la-own.Tpo -c -o libzmq_la-own.lo `test -f 'own.cpp' || echo '$(srcdir)/'`own.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-own.Tpo $(DEPDIR)/libzmq_la-own.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='own.cpp' object='libzmq_la-own.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-own.lo `test -f 'own.cpp' || echo '$(srcdir)/'`own.cpp - -libzmq_la-pair.lo: pair.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pair.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pair.Tpo -c -o libzmq_la-pair.lo `test -f 'pair.cpp' || echo '$(srcdir)/'`pair.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pair.Tpo $(DEPDIR)/libzmq_la-pair.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pair.cpp' object='libzmq_la-pair.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pair.lo `test -f 'pair.cpp' || echo '$(srcdir)/'`pair.cpp - -libzmq_la-pgm_receiver.lo: pgm_receiver.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pgm_receiver.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pgm_receiver.Tpo -c -o libzmq_la-pgm_receiver.lo `test -f 'pgm_receiver.cpp' || echo '$(srcdir)/'`pgm_receiver.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pgm_receiver.Tpo $(DEPDIR)/libzmq_la-pgm_receiver.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pgm_receiver.cpp' object='libzmq_la-pgm_receiver.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pgm_receiver.lo `test -f 'pgm_receiver.cpp' || echo '$(srcdir)/'`pgm_receiver.cpp - -libzmq_la-pgm_sender.lo: pgm_sender.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pgm_sender.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pgm_sender.Tpo -c -o libzmq_la-pgm_sender.lo `test -f 'pgm_sender.cpp' || echo '$(srcdir)/'`pgm_sender.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pgm_sender.Tpo $(DEPDIR)/libzmq_la-pgm_sender.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pgm_sender.cpp' object='libzmq_la-pgm_sender.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pgm_sender.lo `test -f 'pgm_sender.cpp' || echo '$(srcdir)/'`pgm_sender.cpp - -libzmq_la-pgm_socket.lo: pgm_socket.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pgm_socket.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pgm_socket.Tpo -c -o libzmq_la-pgm_socket.lo `test -f 'pgm_socket.cpp' || echo '$(srcdir)/'`pgm_socket.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pgm_socket.Tpo $(DEPDIR)/libzmq_la-pgm_socket.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pgm_socket.cpp' object='libzmq_la-pgm_socket.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pgm_socket.lo `test -f 'pgm_socket.cpp' || echo '$(srcdir)/'`pgm_socket.cpp - -libzmq_la-pipe.lo: pipe.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pipe.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pipe.Tpo -c -o libzmq_la-pipe.lo `test -f 'pipe.cpp' || echo '$(srcdir)/'`pipe.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pipe.Tpo $(DEPDIR)/libzmq_la-pipe.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pipe.cpp' object='libzmq_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pipe.lo `test -f 'pipe.cpp' || echo '$(srcdir)/'`pipe.cpp - -libzmq_la-plain_mechanism.lo: plain_mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-plain_mechanism.lo -MD -MP -MF $(DEPDIR)/libzmq_la-plain_mechanism.Tpo -c -o libzmq_la-plain_mechanism.lo `test -f 'plain_mechanism.cpp' || echo '$(srcdir)/'`plain_mechanism.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-plain_mechanism.Tpo $(DEPDIR)/libzmq_la-plain_mechanism.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plain_mechanism.cpp' object='libzmq_la-plain_mechanism.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-plain_mechanism.lo `test -f 'plain_mechanism.cpp' || echo '$(srcdir)/'`plain_mechanism.cpp - -libzmq_la-poll.lo: poll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-poll.lo -MD -MP -MF $(DEPDIR)/libzmq_la-poll.Tpo -c -o libzmq_la-poll.lo `test -f 'poll.cpp' || echo '$(srcdir)/'`poll.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-poll.Tpo $(DEPDIR)/libzmq_la-poll.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='poll.cpp' object='libzmq_la-poll.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-poll.lo `test -f 'poll.cpp' || echo '$(srcdir)/'`poll.cpp - -libzmq_la-poller_base.lo: poller_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-poller_base.lo -MD -MP -MF $(DEPDIR)/libzmq_la-poller_base.Tpo -c -o libzmq_la-poller_base.lo `test -f 'poller_base.cpp' || echo '$(srcdir)/'`poller_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-poller_base.Tpo $(DEPDIR)/libzmq_la-poller_base.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='poller_base.cpp' object='libzmq_la-poller_base.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-poller_base.lo `test -f 'poller_base.cpp' || echo '$(srcdir)/'`poller_base.cpp - -libzmq_la-pull.lo: pull.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pull.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pull.Tpo -c -o libzmq_la-pull.lo `test -f 'pull.cpp' || echo '$(srcdir)/'`pull.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pull.Tpo $(DEPDIR)/libzmq_la-pull.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pull.cpp' object='libzmq_la-pull.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pull.lo `test -f 'pull.cpp' || echo '$(srcdir)/'`pull.cpp - -libzmq_la-push.lo: push.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-push.lo -MD -MP -MF $(DEPDIR)/libzmq_la-push.Tpo -c -o libzmq_la-push.lo `test -f 'push.cpp' || echo '$(srcdir)/'`push.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-push.Tpo $(DEPDIR)/libzmq_la-push.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='push.cpp' object='libzmq_la-push.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-push.lo `test -f 'push.cpp' || echo '$(srcdir)/'`push.cpp - -libzmq_la-proxy.lo: proxy.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-proxy.lo -MD -MP -MF $(DEPDIR)/libzmq_la-proxy.Tpo -c -o libzmq_la-proxy.lo `test -f 'proxy.cpp' || echo '$(srcdir)/'`proxy.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-proxy.Tpo $(DEPDIR)/libzmq_la-proxy.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='proxy.cpp' object='libzmq_la-proxy.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-proxy.lo `test -f 'proxy.cpp' || echo '$(srcdir)/'`proxy.cpp - -libzmq_la-reaper.lo: reaper.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-reaper.lo -MD -MP -MF $(DEPDIR)/libzmq_la-reaper.Tpo -c -o libzmq_la-reaper.lo `test -f 'reaper.cpp' || echo '$(srcdir)/'`reaper.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-reaper.Tpo $(DEPDIR)/libzmq_la-reaper.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='reaper.cpp' object='libzmq_la-reaper.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-reaper.lo `test -f 'reaper.cpp' || echo '$(srcdir)/'`reaper.cpp - -libzmq_la-pub.lo: pub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-pub.lo -MD -MP -MF $(DEPDIR)/libzmq_la-pub.Tpo -c -o libzmq_la-pub.lo `test -f 'pub.cpp' || echo '$(srcdir)/'`pub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-pub.Tpo $(DEPDIR)/libzmq_la-pub.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pub.cpp' object='libzmq_la-pub.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-pub.lo `test -f 'pub.cpp' || echo '$(srcdir)/'`pub.cpp - -libzmq_la-random.lo: random.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-random.lo -MD -MP -MF $(DEPDIR)/libzmq_la-random.Tpo -c -o libzmq_la-random.lo `test -f 'random.cpp' || echo '$(srcdir)/'`random.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-random.Tpo $(DEPDIR)/libzmq_la-random.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='random.cpp' object='libzmq_la-random.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-random.lo `test -f 'random.cpp' || echo '$(srcdir)/'`random.cpp - -libzmq_la-rep.lo: rep.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-rep.lo -MD -MP -MF $(DEPDIR)/libzmq_la-rep.Tpo -c -o libzmq_la-rep.lo `test -f 'rep.cpp' || echo '$(srcdir)/'`rep.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-rep.Tpo $(DEPDIR)/libzmq_la-rep.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rep.cpp' object='libzmq_la-rep.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-rep.lo `test -f 'rep.cpp' || echo '$(srcdir)/'`rep.cpp - -libzmq_la-req.lo: req.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-req.lo -MD -MP -MF $(DEPDIR)/libzmq_la-req.Tpo -c -o libzmq_la-req.lo `test -f 'req.cpp' || echo '$(srcdir)/'`req.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-req.Tpo $(DEPDIR)/libzmq_la-req.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='req.cpp' object='libzmq_la-req.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-req.lo `test -f 'req.cpp' || echo '$(srcdir)/'`req.cpp - -libzmq_la-select.lo: select.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-select.lo -MD -MP -MF $(DEPDIR)/libzmq_la-select.Tpo -c -o libzmq_la-select.lo `test -f 'select.cpp' || echo '$(srcdir)/'`select.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-select.Tpo $(DEPDIR)/libzmq_la-select.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='select.cpp' object='libzmq_la-select.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-select.lo `test -f 'select.cpp' || echo '$(srcdir)/'`select.cpp - -libzmq_la-session_base.lo: session_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-session_base.lo -MD -MP -MF $(DEPDIR)/libzmq_la-session_base.Tpo -c -o libzmq_la-session_base.lo `test -f 'session_base.cpp' || echo '$(srcdir)/'`session_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-session_base.Tpo $(DEPDIR)/libzmq_la-session_base.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_base.cpp' object='libzmq_la-session_base.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-session_base.lo `test -f 'session_base.cpp' || echo '$(srcdir)/'`session_base.cpp - -libzmq_la-signaler.lo: signaler.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-signaler.lo -MD -MP -MF $(DEPDIR)/libzmq_la-signaler.Tpo -c -o libzmq_la-signaler.lo `test -f 'signaler.cpp' || echo '$(srcdir)/'`signaler.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-signaler.Tpo $(DEPDIR)/libzmq_la-signaler.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='signaler.cpp' object='libzmq_la-signaler.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-signaler.lo `test -f 'signaler.cpp' || echo '$(srcdir)/'`signaler.cpp - -libzmq_la-socket_base.lo: socket_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-socket_base.lo -MD -MP -MF $(DEPDIR)/libzmq_la-socket_base.Tpo -c -o libzmq_la-socket_base.lo `test -f 'socket_base.cpp' || echo '$(srcdir)/'`socket_base.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-socket_base.Tpo $(DEPDIR)/libzmq_la-socket_base.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='socket_base.cpp' object='libzmq_la-socket_base.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-socket_base.lo `test -f 'socket_base.cpp' || echo '$(srcdir)/'`socket_base.cpp - -libzmq_la-stream.lo: stream.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-stream.lo -MD -MP -MF $(DEPDIR)/libzmq_la-stream.Tpo -c -o libzmq_la-stream.lo `test -f 'stream.cpp' || echo '$(srcdir)/'`stream.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-stream.Tpo $(DEPDIR)/libzmq_la-stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stream.cpp' object='libzmq_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-stream.lo `test -f 'stream.cpp' || echo '$(srcdir)/'`stream.cpp - -libzmq_la-stream_engine.lo: stream_engine.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-stream_engine.lo -MD -MP -MF $(DEPDIR)/libzmq_la-stream_engine.Tpo -c -o libzmq_la-stream_engine.lo `test -f 'stream_engine.cpp' || echo '$(srcdir)/'`stream_engine.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-stream_engine.Tpo $(DEPDIR)/libzmq_la-stream_engine.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stream_engine.cpp' object='libzmq_la-stream_engine.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-stream_engine.lo `test -f 'stream_engine.cpp' || echo '$(srcdir)/'`stream_engine.cpp - -libzmq_la-sub.lo: sub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-sub.lo -MD -MP -MF $(DEPDIR)/libzmq_la-sub.Tpo -c -o libzmq_la-sub.lo `test -f 'sub.cpp' || echo '$(srcdir)/'`sub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-sub.Tpo $(DEPDIR)/libzmq_la-sub.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sub.cpp' object='libzmq_la-sub.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-sub.lo `test -f 'sub.cpp' || echo '$(srcdir)/'`sub.cpp - -libzmq_la-tcp.lo: tcp.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-tcp.lo -MD -MP -MF $(DEPDIR)/libzmq_la-tcp.Tpo -c -o libzmq_la-tcp.lo `test -f 'tcp.cpp' || echo '$(srcdir)/'`tcp.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-tcp.Tpo $(DEPDIR)/libzmq_la-tcp.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tcp.cpp' object='libzmq_la-tcp.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-tcp.lo `test -f 'tcp.cpp' || echo '$(srcdir)/'`tcp.cpp - -libzmq_la-tcp_address.lo: tcp_address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-tcp_address.lo -MD -MP -MF $(DEPDIR)/libzmq_la-tcp_address.Tpo -c -o libzmq_la-tcp_address.lo `test -f 'tcp_address.cpp' || echo '$(srcdir)/'`tcp_address.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-tcp_address.Tpo $(DEPDIR)/libzmq_la-tcp_address.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tcp_address.cpp' object='libzmq_la-tcp_address.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-tcp_address.lo `test -f 'tcp_address.cpp' || echo '$(srcdir)/'`tcp_address.cpp - -libzmq_la-tcp_connecter.lo: tcp_connecter.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-tcp_connecter.lo -MD -MP -MF $(DEPDIR)/libzmq_la-tcp_connecter.Tpo -c -o libzmq_la-tcp_connecter.lo `test -f 'tcp_connecter.cpp' || echo '$(srcdir)/'`tcp_connecter.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-tcp_connecter.Tpo $(DEPDIR)/libzmq_la-tcp_connecter.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tcp_connecter.cpp' object='libzmq_la-tcp_connecter.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-tcp_connecter.lo `test -f 'tcp_connecter.cpp' || echo '$(srcdir)/'`tcp_connecter.cpp - -libzmq_la-tcp_listener.lo: tcp_listener.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-tcp_listener.lo -MD -MP -MF $(DEPDIR)/libzmq_la-tcp_listener.Tpo -c -o libzmq_la-tcp_listener.lo `test -f 'tcp_listener.cpp' || echo '$(srcdir)/'`tcp_listener.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-tcp_listener.Tpo $(DEPDIR)/libzmq_la-tcp_listener.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tcp_listener.cpp' object='libzmq_la-tcp_listener.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-tcp_listener.lo `test -f 'tcp_listener.cpp' || echo '$(srcdir)/'`tcp_listener.cpp - -libzmq_la-thread.lo: thread.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-thread.lo -MD -MP -MF $(DEPDIR)/libzmq_la-thread.Tpo -c -o libzmq_la-thread.lo `test -f 'thread.cpp' || echo '$(srcdir)/'`thread.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-thread.Tpo $(DEPDIR)/libzmq_la-thread.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='thread.cpp' object='libzmq_la-thread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-thread.lo `test -f 'thread.cpp' || echo '$(srcdir)/'`thread.cpp - -libzmq_la-trie.lo: trie.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-trie.lo -MD -MP -MF $(DEPDIR)/libzmq_la-trie.Tpo -c -o libzmq_la-trie.lo `test -f 'trie.cpp' || echo '$(srcdir)/'`trie.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-trie.Tpo $(DEPDIR)/libzmq_la-trie.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='trie.cpp' object='libzmq_la-trie.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-trie.lo `test -f 'trie.cpp' || echo '$(srcdir)/'`trie.cpp - -libzmq_la-xpub.lo: xpub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-xpub.lo -MD -MP -MF $(DEPDIR)/libzmq_la-xpub.Tpo -c -o libzmq_la-xpub.lo `test -f 'xpub.cpp' || echo '$(srcdir)/'`xpub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-xpub.Tpo $(DEPDIR)/libzmq_la-xpub.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xpub.cpp' object='libzmq_la-xpub.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-xpub.lo `test -f 'xpub.cpp' || echo '$(srcdir)/'`xpub.cpp - -libzmq_la-router.lo: router.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-router.lo -MD -MP -MF $(DEPDIR)/libzmq_la-router.Tpo -c -o libzmq_la-router.lo `test -f 'router.cpp' || echo '$(srcdir)/'`router.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-router.Tpo $(DEPDIR)/libzmq_la-router.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='router.cpp' object='libzmq_la-router.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-router.lo `test -f 'router.cpp' || echo '$(srcdir)/'`router.cpp - -libzmq_la-dealer.lo: dealer.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-dealer.lo -MD -MP -MF $(DEPDIR)/libzmq_la-dealer.Tpo -c -o libzmq_la-dealer.lo `test -f 'dealer.cpp' || echo '$(srcdir)/'`dealer.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-dealer.Tpo $(DEPDIR)/libzmq_la-dealer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dealer.cpp' object='libzmq_la-dealer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-dealer.lo `test -f 'dealer.cpp' || echo '$(srcdir)/'`dealer.cpp - -libzmq_la-v1_decoder.lo: v1_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-v1_decoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-v1_decoder.Tpo -c -o libzmq_la-v1_decoder.lo `test -f 'v1_decoder.cpp' || echo '$(srcdir)/'`v1_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-v1_decoder.Tpo $(DEPDIR)/libzmq_la-v1_decoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='v1_decoder.cpp' object='libzmq_la-v1_decoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-v1_decoder.lo `test -f 'v1_decoder.cpp' || echo '$(srcdir)/'`v1_decoder.cpp - -libzmq_la-v1_encoder.lo: v1_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-v1_encoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-v1_encoder.Tpo -c -o libzmq_la-v1_encoder.lo `test -f 'v1_encoder.cpp' || echo '$(srcdir)/'`v1_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-v1_encoder.Tpo $(DEPDIR)/libzmq_la-v1_encoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='v1_encoder.cpp' object='libzmq_la-v1_encoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-v1_encoder.lo `test -f 'v1_encoder.cpp' || echo '$(srcdir)/'`v1_encoder.cpp - -libzmq_la-v2_decoder.lo: v2_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-v2_decoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-v2_decoder.Tpo -c -o libzmq_la-v2_decoder.lo `test -f 'v2_decoder.cpp' || echo '$(srcdir)/'`v2_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-v2_decoder.Tpo $(DEPDIR)/libzmq_la-v2_decoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='v2_decoder.cpp' object='libzmq_la-v2_decoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-v2_decoder.lo `test -f 'v2_decoder.cpp' || echo '$(srcdir)/'`v2_decoder.cpp - -libzmq_la-v2_encoder.lo: v2_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-v2_encoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-v2_encoder.Tpo -c -o libzmq_la-v2_encoder.lo `test -f 'v2_encoder.cpp' || echo '$(srcdir)/'`v2_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-v2_encoder.Tpo $(DEPDIR)/libzmq_la-v2_encoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='v2_encoder.cpp' object='libzmq_la-v2_encoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-v2_encoder.lo `test -f 'v2_encoder.cpp' || echo '$(srcdir)/'`v2_encoder.cpp - -libzmq_la-xsub.lo: xsub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-xsub.lo -MD -MP -MF $(DEPDIR)/libzmq_la-xsub.Tpo -c -o libzmq_la-xsub.lo `test -f 'xsub.cpp' || echo '$(srcdir)/'`xsub.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-xsub.Tpo $(DEPDIR)/libzmq_la-xsub.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xsub.cpp' object='libzmq_la-xsub.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-xsub.lo `test -f 'xsub.cpp' || echo '$(srcdir)/'`xsub.cpp - -libzmq_la-zmq.lo: zmq.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-zmq.lo -MD -MP -MF $(DEPDIR)/libzmq_la-zmq.Tpo -c -o libzmq_la-zmq.lo `test -f 'zmq.cpp' || echo '$(srcdir)/'`zmq.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-zmq.Tpo $(DEPDIR)/libzmq_la-zmq.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zmq.cpp' object='libzmq_la-zmq.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-zmq.lo `test -f 'zmq.cpp' || echo '$(srcdir)/'`zmq.cpp - -libzmq_la-zmq_utils.lo: zmq_utils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-zmq_utils.lo -MD -MP -MF $(DEPDIR)/libzmq_la-zmq_utils.Tpo -c -o libzmq_la-zmq_utils.lo `test -f 'zmq_utils.cpp' || echo '$(srcdir)/'`zmq_utils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-zmq_utils.Tpo $(DEPDIR)/libzmq_la-zmq_utils.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zmq_utils.cpp' object='libzmq_la-zmq_utils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-zmq_utils.lo `test -f 'zmq_utils.cpp' || echo '$(srcdir)/'`zmq_utils.cpp - -libzmq_la-raw_decoder.lo: raw_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-raw_decoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-raw_decoder.Tpo -c -o libzmq_la-raw_decoder.lo `test -f 'raw_decoder.cpp' || echo '$(srcdir)/'`raw_decoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-raw_decoder.Tpo $(DEPDIR)/libzmq_la-raw_decoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='raw_decoder.cpp' object='libzmq_la-raw_decoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-raw_decoder.lo `test -f 'raw_decoder.cpp' || echo '$(srcdir)/'`raw_decoder.cpp - -libzmq_la-raw_encoder.lo: raw_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -MT libzmq_la-raw_encoder.lo -MD -MP -MF $(DEPDIR)/libzmq_la-raw_encoder.Tpo -c -o libzmq_la-raw_encoder.lo `test -f 'raw_encoder.cpp' || echo '$(srcdir)/'`raw_encoder.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libzmq_la-raw_encoder.Tpo $(DEPDIR)/libzmq_la-raw_encoder.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='raw_encoder.cpp' object='libzmq_la-raw_encoder.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libzmq_la_CPPFLAGS) $(CPPFLAGS) $(libzmq_la_CXXFLAGS) $(CXXFLAGS) -c -o libzmq_la-raw_encoder.lo `test -f 'raw_encoder.cpp' || echo '$(srcdir)/'`raw_encoder.cpp - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-pkgconfigDATA: $(pkgconfig_DATA) - @$(NORMAL_INSTALL) - test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ - done - -uninstall-pkgconfigDATA: - @$(NORMAL_UNINSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) -install-includeHEADERS: $(include_HEADERS) - @$(NORMAL_INSTALL) - test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" - @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ - done - -uninstall-includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) platform.hpp.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) platform.hpp.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) platform.hpp.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) platform.hpp.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) platform.hpp -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-includeHEADERS install-pkgconfigDATA - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \ - uninstall-pkgconfigDATA - -.MAKE: all install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags dist-hook distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am \ - install-includeHEADERS install-info install-info-am \ - install-libLTLIBRARIES install-man install-pdf install-pdf-am \ - install-pkgconfigDATA install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES uninstall-pkgconfigDATA - - -dist-hook: - -rm $(distdir)/platform.hpp - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/address.cpp b/src/address.cpp deleted file mode 100644 index a7b7761..0000000 --- a/src/address.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "address.hpp" -#include "err.hpp" -#include "tcp_address.hpp" -#include "ipc_address.hpp" - -#include <string> -#include <sstream> - -zmq::address_t::address_t ( - const std::string &protocol_, const std::string &address_) - : protocol (protocol_), - address (address_) -{ - memset (&resolved, 0, sizeof (resolved)); -} - -zmq::address_t::~address_t () -{ - if (protocol == "tcp") { - if (resolved.tcp_addr) { - delete resolved.tcp_addr; - resolved.tcp_addr = 0; - } - } -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - else - if (protocol == "ipc") { - if (resolved.ipc_addr) { - delete resolved.ipc_addr; - resolved.ipc_addr = 0; - } - } -#endif -} - -int zmq::address_t::to_string (std::string &addr_) const -{ - if (protocol == "tcp") { - if (resolved.tcp_addr) - return resolved.tcp_addr->to_string(addr_); - } -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - else - if (protocol == "ipc") { - if (resolved.ipc_addr) - return resolved.ipc_addr->to_string(addr_); - } -#endif - - if (!protocol.empty () && !address.empty ()) { - std::stringstream s; - s << protocol << "://" << address; - addr_ = s.str (); - return 0; - } - addr_.clear (); - return -1; -} diff --git a/src/address.hpp b/src/address.hpp deleted file mode 100644 index f84c6cc..0000000 --- a/src/address.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ADDRESS_HPP_INCLUDED__ -#define __ZMQ_ADDRESS_HPP_INCLUDED__ - -#include <string> - -namespace zmq -{ - class tcp_address_t; -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - class ipc_address_t; -#endif - struct address_t { - address_t (const std::string &protocol_, const std::string &address_); - - ~address_t (); - - const std::string protocol; - const std::string address; - - // Protocol specific resolved address - union { - tcp_address_t *tcp_addr; -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - ipc_address_t *ipc_addr; -#endif - } resolved; - - int to_string (std::string &addr_) const; - }; -} - -#endif diff --git a/src/array.hpp b/src/array.hpp deleted file mode 100644 index 0b5b4e3..0000000 --- a/src/array.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ARRAY_INCLUDED__ -#define __ZMQ_ARRAY_INCLUDED__ - -#include <vector> -#include <algorithm> - -namespace zmq -{ - - // Base class for objects stored in the array. If you want to store - // same object in mutliple arrays, each of those arrays has to have - // different ID. The item itself has to be derived from instantiations of - // array_item_t template for all relevant IDs. - - template <int ID = 0> class array_item_t - { - public: - - inline array_item_t () : - array_index (-1) - { - } - - // The destructor doesn't have to be virtual. It is mad virtual - // just to keep ICC and code checking tools from complaining. - inline virtual ~array_item_t () - { - } - - inline void set_array_index (int index_) - { - array_index = index_; - } - - inline int get_array_index () - { - return array_index; - } - - private: - - int array_index; - - array_item_t (const array_item_t&); - const array_item_t &operator = (const array_item_t&); - }; - - // Fast array implementation with O(1) access to item, insertion and - // removal. Array stores pointers rather than objects. The objects have - // to be derived from array_item_t<ID> class. - - template <typename T, int ID = 0> class array_t - { - private: - - typedef array_item_t <ID> item_t; - - public: - - typedef typename std::vector <T*>::size_type size_type; - - inline array_t () - { - } - - inline ~array_t () - { - } - - inline size_type size () - { - return items.size (); - } - - inline bool empty () - { - return items.empty (); - } - - inline T *&operator [] (size_type index_) - { - return items [index_]; - } - - inline void push_back (T *item_) - { - if (item_) - ((item_t*) item_)->set_array_index ((int) items.size ()); - items.push_back (item_); - } - - inline void erase (T *item_) { - erase (((item_t*) item_)->get_array_index ()); - } - - inline void erase (size_type index_) { - if (items.back ()) - ((item_t*) items.back ())->set_array_index ((int) index_); - items [index_] = items.back (); - items.pop_back (); - } - - inline void swap (size_type index1_, size_type index2_) - { - if (items [index1_]) - ((item_t*) items [index1_])->set_array_index ((int) index2_); - if (items [index2_]) - ((item_t*) items [index2_])->set_array_index ((int) index1_); - std::swap (items [index1_], items [index2_]); - } - - inline void clear () - { - items.clear (); - } - - inline size_type index (T *item_) - { - return (size_type) ((item_t*) item_)->get_array_index (); - } - - private: - - typedef std::vector <T*> items_t; - items_t items; - - array_t (const array_t&); - const array_t &operator = (const array_t&); - }; - -} - -#endif - diff --git a/src/atomic_counter.hpp b/src/atomic_counter.hpp deleted file mode 100644 index 45cfe88..0000000 --- a/src/atomic_counter.hpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__ -#define __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__ - -#include "stdint.hpp" -#include "platform.hpp" - -#if defined ZMQ_FORCE_MUTEXES -#define ZMQ_ATOMIC_COUNTER_MUTEX -#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ -#define ZMQ_ATOMIC_COUNTER_X86 -#elif defined __ARM_ARCH_7A__ && defined __GNUC__ -#define ZMQ_ATOMIC_COUNTER_ARM -#elif defined ZMQ_HAVE_WINDOWS -#define ZMQ_ATOMIC_COUNTER_WINDOWS -#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD) -#define ZMQ_ATOMIC_COUNTER_ATOMIC_H -#elif defined __tile__ -#define ZMQ_ATOMIC_COUNTER_TILE -#else -#define ZMQ_ATOMIC_COUNTER_MUTEX -#endif - -#if defined ZMQ_ATOMIC_COUNTER_MUTEX -#include "mutex.hpp" -#elif defined ZMQ_ATOMIC_COUNTER_WINDOWS -#include "windows.hpp" -#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H -#include <atomic.h> -#elif defined ZMQ_ATOMIC_COUNTER_TILE -#include <arch/atomic.h> -#endif - -namespace zmq -{ - - // This class represents an integer that can be incremented/decremented - // in atomic fashion. - - class atomic_counter_t - { - public: - - typedef uint32_t integer_t; - - inline atomic_counter_t (integer_t value_ = 0) : - value (value_) - { - } - - inline ~atomic_counter_t () - { - } - - // Set counter value (not thread-safe). - inline void set (integer_t value_) - { - value = value_; - } - - // Atomic addition. Returns the old value. - inline integer_t add (integer_t increment_) - { - integer_t old_value; - -#if defined ZMQ_ATOMIC_COUNTER_WINDOWS - old_value = InterlockedExchangeAdd ((LONG*) &value, increment_); -#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H - integer_t new_value = atomic_add_32_nv (&value, increment_); - old_value = new_value - increment_; -#elif defined ZMQ_ATOMIC_COUNTER_TILE - old_value = arch_atomic_add (&value, increment_); -#elif defined ZMQ_ATOMIC_COUNTER_X86 - __asm__ volatile ( - "lock; xadd %0, %1 \n\t" - : "=r" (old_value), "=m" (value) - : "0" (increment_), "m" (value) - : "cc", "memory"); -#elif defined ZMQ_ATOMIC_COUNTER_ARM - integer_t flag, tmp; - __asm__ volatile ( - " dmb sy\n\t" - "1: ldrex %0, [%5]\n\t" - " add %2, %0, %4\n\t" - " strex %1, %2, [%5]\n\t" - " teq %1, #0\n\t" - " bne 1b\n\t" - " dmb sy\n\t" - : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value) - : "Ir"(increment_), "r"(&value) - : "cc"); -#elif defined ZMQ_ATOMIC_COUNTER_MUTEX - sync.lock (); - old_value = value; - value += increment_; - sync.unlock (); -#else -#error atomic_counter is not implemented for this platform -#endif - return old_value; - } - - // Atomic subtraction. Returns false if the counter drops to zero. - inline bool sub (integer_t decrement) - { -#if defined ZMQ_ATOMIC_COUNTER_WINDOWS - LONG delta = - ((LONG) decrement); - integer_t old = InterlockedExchangeAdd ((LONG*) &value, delta); - return old - decrement != 0; -#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H - int32_t delta = - ((int32_t) decrement); - integer_t nv = atomic_add_32_nv (&value, delta); - return nv != 0; -#elif defined ZMQ_ATOMIC_COUNTER_TILE - int32_t delta = - ((int32_t) decrement); - integer_t nv = arch_atomic_add (&value, delta); - return nv != 0; -#elif defined ZMQ_ATOMIC_COUNTER_X86 - integer_t oldval = -decrement; - volatile integer_t *val = &value; - __asm__ volatile ("lock; xaddl %0,%1" - : "=r" (oldval), "=m" (*val) - : "0" (oldval), "m" (*val) - : "cc", "memory"); - return oldval != decrement; -#elif defined ZMQ_ATOMIC_COUNTER_ARM - integer_t old_value, flag, tmp; - __asm__ volatile ( - " dmb sy\n\t" - "1: ldrex %0, [%5]\n\t" - " sub %2, %0, %4\n\t" - " strex %1, %2, [%5]\n\t" - " teq %1, #0\n\t" - " bne 1b\n\t" - " dmb sy\n\t" - : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value) - : "Ir"(decrement), "r"(&value) - : "cc"); - return old_value - decrement != 0; -#elif defined ZMQ_ATOMIC_COUNTER_MUTEX - sync.lock (); - value -= decrement; - bool result = value ? true : false; - sync.unlock (); - return result; -#else -#error atomic_counter is not implemented for this platform -#endif - } - - inline integer_t get () - { - return value; - } - - private: - - volatile integer_t value; -#if defined ZMQ_ATOMIC_COUNTER_MUTEX - mutex_t sync; -#endif - - atomic_counter_t (const atomic_counter_t&); - const atomic_counter_t& operator = (const atomic_counter_t&); - }; - -} - -// Remove macros local to this file. -#if defined ZMQ_ATOMIC_COUNTER_WINDOWS -#undef ZMQ_ATOMIC_COUNTER_WINDOWS -#endif -#if defined ZMQ_ATOMIC_COUNTER_ATOMIC_H -#undef ZMQ_ATOMIC_COUNTER_ATOMIC_H -#endif -#if defined ZMQ_ATOMIC_COUNTER_X86 -#undef ZMQ_ATOMIC_COUNTER_X86 -#endif -#if defined ZMQ_ATOMIC_COUNTER_ARM -#undef ZMQ_ATOMIC_COUNTER_ARM -#endif -#if defined ZMQ_ATOMIC_COUNTER_MUTEX -#undef ZMQ_ATOMIC_COUNTER_MUTEX -#endif - -#endif - diff --git a/src/atomic_ptr.hpp b/src/atomic_ptr.hpp deleted file mode 100644 index 066d54b..0000000 --- a/src/atomic_ptr.hpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ATOMIC_PTR_HPP_INCLUDED__ -#define __ZMQ_ATOMIC_PTR_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_FORCE_MUTEXES -#define ZMQ_ATOMIC_PTR_MUTEX -#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ -#define ZMQ_ATOMIC_PTR_X86 -#elif defined __ARM_ARCH_7A__ && defined __GNUC__ -#define ZMQ_ATOMIC_PTR_ARM -#elif defined __tile__ -#define ZMQ_ATOMIC_PTR_TILE -#elif defined ZMQ_HAVE_WINDOWS -#define ZMQ_ATOMIC_PTR_WINDOWS -#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD) -#define ZMQ_ATOMIC_PTR_ATOMIC_H -#else -#define ZMQ_ATOMIC_PTR_MUTEX -#endif - -#if defined ZMQ_ATOMIC_PTR_MUTEX -#include "mutex.hpp" -#elif defined ZMQ_ATOMIC_PTR_WINDOWS -#include "windows.hpp" -#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H -#include <atomic.h> -#elif defined ZMQ_ATOMIC_PTR_TILE -#include <arch/atomic.h> -#endif - -namespace zmq -{ - - // This class encapsulates several atomic operations on pointers. - - template <typename T> class atomic_ptr_t - { - public: - - // Initialise atomic pointer - inline atomic_ptr_t () - { - ptr = NULL; - } - - // Destroy atomic pointer - inline ~atomic_ptr_t () - { - } - - // Set value of atomic pointer in a non-threadsafe way - // Use this function only when you are sure that at most one - // thread is accessing the pointer at the moment. - inline void set (T *ptr_) - { - this->ptr = ptr_; - } - - // Perform atomic 'exchange pointers' operation. Pointer is set - // to the 'val' value. Old value is returned. - inline T *xchg (T *val_) - { -#if defined ZMQ_ATOMIC_PTR_WINDOWS - return (T*) InterlockedExchangePointer ((PVOID*) &ptr, val_); -#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H - return (T*) atomic_swap_ptr (&ptr, val_); -#elif defined ZMQ_ATOMIC_PTR_TILE - return (T*) arch_atomic_exchange (&ptr, val_); -#elif defined ZMQ_ATOMIC_PTR_X86 - T *old; - __asm__ volatile ( - "lock; xchg %0, %2" - : "=r" (old), "=m" (ptr) - : "m" (ptr), "0" (val_)); - return old; -#elif defined ZMQ_ATOMIC_PTR_ARM - T* old; - unsigned int flag; - __asm__ volatile ( - " dmb sy\n\t" - "1: ldrex %1, [%3]\n\t" - " strex %0, %4, [%3]\n\t" - " teq %0, #0\n\t" - " bne 1b\n\t" - " dmb sy\n\t" - : "=&r"(flag), "=&r"(old), "+Qo"(ptr) - : "r"(&ptr), "r"(val_) - : "cc"); - return old; -#elif defined ZMQ_ATOMIC_PTR_MUTEX - sync.lock (); - T *old = (T*) ptr; - ptr = val_; - sync.unlock (); - return old; -#else -#error atomic_ptr is not implemented for this platform -#endif - } - - // Perform atomic 'compare and swap' operation on the pointer. - // The pointer is compared to 'cmp' argument and if they are - // equal, its value is set to 'val'. Old value of the pointer - // is returned. - inline T *cas (T *cmp_, T *val_) - { -#if defined ZMQ_ATOMIC_PTR_WINDOWS - return (T*) InterlockedCompareExchangePointer ( - (volatile PVOID*) &ptr, val_, cmp_); -#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H - return (T*) atomic_cas_ptr (&ptr, cmp_, val_); -#elif defined ZMQ_ATOMIC_PTR_TILE - return (T*) arch_atomic_val_compare_and_exchange (&ptr, cmp_, val_); -#elif defined ZMQ_ATOMIC_PTR_X86 - T *old; - __asm__ volatile ( - "lock; cmpxchg %2, %3" - : "=a" (old), "=m" (ptr) - : "r" (val_), "m" (ptr), "0" (cmp_) - : "cc"); - return old; -#elif defined ZMQ_ATOMIC_PTR_ARM - T *old; - unsigned int flag; - __asm__ volatile ( - " dmb sy\n\t" - "1: ldrex %1, [%3]\n\t" - " mov %0, #0\n\t" - " teq %1, %4\n\t" - " it eq\n\t" - " strexeq %0, %5, [%3]\n\t" - " teq %0, #0\n\t" - " bne 1b\n\t" - " dmb sy\n\t" - : "=&r"(flag), "=&r"(old), "+Qo"(ptr) - : "r"(&ptr), "r"(cmp_), "r"(val_) - : "cc"); - return old; -#elif defined ZMQ_ATOMIC_PTR_MUTEX - sync.lock (); - T *old = (T*) ptr; - if (ptr == cmp_) - ptr = val_; - sync.unlock (); - return old; -#else -#error atomic_ptr is not implemented for this platform -#endif - } - - private: - - volatile T *ptr; -#if defined ZMQ_ATOMIC_PTR_MUTEX - mutex_t sync; -#endif - - atomic_ptr_t (const atomic_ptr_t&); - const atomic_ptr_t &operator = (const atomic_ptr_t&); - }; - -} - -// Remove macros local to this file. -#if defined ZMQ_ATOMIC_PTR_WINDOWS -#undef ZMQ_ATOMIC_PTR_WINDOWS -#endif -#if defined ZMQ_ATOMIC_PTR_ATOMIC_H -#undef ZMQ_ATOMIC_PTR_ATOMIC_H -#endif -#if defined ZMQ_ATOMIC_PTR_X86 -#undef ZMQ_ATOMIC_PTR_X86 -#endif -#if defined ZMQ_ATOMIC_PTR_ARM -#undef ZMQ_ATOMIC_PTR_ARM -#endif -#if defined ZMQ_ATOMIC_PTR_MUTEX -#undef ZMQ_ATOMIC_PTR_MUTEX -#endif - -#endif - diff --git a/src/blob.hpp b/src/blob.hpp deleted file mode 100644 index 65d305b..0000000 --- a/src/blob.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_BLOB_HPP_INCLUDED__ -#define __ZMQ_BLOB_HPP_INCLUDED__ - -#include <string> -#include <string.h> - -// Borrowed from id3lib_strings.h: -// They seem to be doing something for MSC, but since I only have gcc, I'll just do that -// Assuming this is uneccessary on GCC 4 -// #if (defined(__GNUC__) && (__GNUC__ >= 3) || (defined(_MSC_VER) && _MSC_VER > 1000)) -#if (defined(__GNUC__) && (__GNUC__ >= 3) && (__GNUC__ <= 4)) -namespace std -{ - template<> - struct char_traits<unsigned char> - { - typedef unsigned char char_type; - // Unsigned as wint_t in unsigned. - typedef unsigned long int_type; - typedef streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; - - static void - assign(char_type& __c1, const char_type& __c2) - { __c1 = __c2; } - - static bool - eq(const char_type& __c1, const char_type& __c2) - { return __c1 == __c2; } - - static bool - lt(const char_type& __c1, const char_type& __c2) - { return __c1 < __c2; } - - static int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - for (size_t __i = 0; __i < __n; ++__i) - if (!eq(__s1[__i], __s2[__i])) - return lt(__s1[__i], __s2[__i]) ? -1 : 1; - return 0; - } - - static size_t - length(const char_type* __s) - { - const char_type* __p = __s; - while (__p) - ++__p; - return (__p - __s); - } - - static const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) - if (*__p == __a) return __p; - return 0; - } - - static char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { return (char_type*) memmove(__s1, __s2, __n * sizeof(char_type)); } - - static char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { return (char_type*) memcpy(__s1, __s2, __n * sizeof(char_type)); } - - static char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - for (char_type* __p = __s; __p < __s + __n; ++__p) - assign(*__p, __a); - return __s; - } - - static char_type - to_char_type(const int_type& __c) - { return char_type(__c); } - - static int_type - to_int_type(const char_type& __c) { return int_type(__c); } - - static bool - eq_int_type(const int_type& __c1, const int_type& __c2) - { return __c1 == __c2; } - - static int_type - eof() { return static_cast<int_type>(-1); } - - static int_type - not_eof(const int_type& __c) - { return eq_int_type(__c, eof()) ? int_type(0) : __c; } - }; - -} // namespace std -#endif // GCC version 3 - - -namespace zmq -{ - - // Object to hold dynamically allocated opaque binary data. - typedef std::basic_string <unsigned char> blob_t; - -} - -#endif - diff --git a/src/clock.cpp b/src/clock.cpp deleted file mode 100644 index 1bc82b0..0000000 --- a/src/clock.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "clock.hpp" -#include "platform.hpp" -#include "likely.hpp" -#include "config.hpp" -#include "err.hpp" -#include "mutex.hpp" - -#include <stddef.h> - -#if defined _MSC_VER -#if defined _WIN32_WCE -#include <cmnintrin.h> -#else -#include <intrin.h> -#endif -#endif - -#if !defined ZMQ_HAVE_WINDOWS -#include <sys/time.h> -#endif - -#if defined HAVE_CLOCK_GETTIME || defined HAVE_GETHRTIME -#include <time.h> -#endif - -#ifdef ZMQ_HAVE_WINDOWS -typedef ULONGLONG (*f_compatible_get_tick_count64)(); - -static zmq::mutex_t compatible_get_tick_count64_mutex; - -ULONGLONG compatible_get_tick_count64() -{ - compatible_get_tick_count64_mutex.lock(); - static DWORD s_wrap = 0; - static DWORD s_last_tick = 0; - const DWORD current_tick = ::GetTickCount(); - if (current_tick < s_last_tick) - ++s_wrap; - - s_last_tick = current_tick; - const ULONGLONG result = (static_cast<ULONGLONG>(s_wrap) << 32) + static_cast<ULONGLONG>(current_tick); - compatible_get_tick_count64_mutex.unlock(); - return result; -} - -f_compatible_get_tick_count64 init_compatible_get_tick_count64() -{ - f_compatible_get_tick_count64 func = NULL; - HMODULE module = ::LoadLibraryA("Kernel32.dll"); - if (module != NULL) - func = reinterpret_cast<f_compatible_get_tick_count64>(::GetProcAddress(module, "GetTickCount64")); - - if (func == NULL) - func = compatible_get_tick_count64; - - return func; -} - -static f_compatible_get_tick_count64 my_get_tick_count64 = init_compatible_get_tick_count64(); -#endif - -zmq::clock_t::clock_t () : - last_tsc (rdtsc ()), -#ifdef ZMQ_HAVE_WINDOWS - last_time (static_cast<uint64_t>((*my_get_tick_count64)())) -#else - last_time (now_us () / 1000) -#endif -{ -} - -zmq::clock_t::~clock_t () -{ -} - -uint64_t zmq::clock_t::now_us () -{ -#if defined ZMQ_HAVE_WINDOWS - - // Get the high resolution counter's accuracy. - LARGE_INTEGER ticksPerSecond; - QueryPerformanceFrequency (&ticksPerSecond); - - // What time is it? - LARGE_INTEGER tick; - QueryPerformanceCounter (&tick); - - // Convert the tick number into the number of seconds - // since the system was started. - double ticks_div = ticksPerSecond.QuadPart / 1000000.0; - return (uint64_t) (tick.QuadPart / ticks_div); - -#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC - - // Use POSIX clock_gettime function to get precise monotonic time. - struct timespec tv; - int rc = clock_gettime (CLOCK_MONOTONIC, &tv); - // Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported. - // This should be a configuration check, but I looked into it and writing an - // AC_FUNC_CLOCK_MONOTONIC seems beyond my powers. - if( rc != 0) { - // Use POSIX gettimeofday function to get precise time. - struct timeval tv; - int rc = gettimeofday (&tv, NULL); - errno_assert (rc == 0); - return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec); - } - return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_nsec / 1000); - -#elif defined HAVE_GETHRTIME - - return (gethrtime () / 1000); - -#else - - // Use POSIX gettimeofday function to get precise time. - struct timeval tv; - int rc = gettimeofday (&tv, NULL); - errno_assert (rc == 0); - return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec); - -#endif -} - -uint64_t zmq::clock_t::now_ms () -{ - uint64_t tsc = rdtsc (); - - // If TSC is not supported, get precise time and chop off the microseconds. - if (!tsc) - { -#ifdef ZMQ_HAVE_WINDOWS - // Under Windows, now_us is not so reliable since QueryPerformanceCounter - // does not guarantee that it will use a hardware that offers a monotonic timer. - // So, lets use GetTickCount when GetTickCount64 is not available with an workaround - // to its 32 bit limitation. - return static_cast<uint64_t>((*my_get_tick_count64)()); -#else - return now_us () / 1000; -#endif - } - - // If TSC haven't jumped back (in case of migration to a different - // CPU core) and if not too much time elapsed since last measurement, - // we can return cached time value. - if (likely (tsc - last_tsc <= (clock_precision / 2) && tsc >= last_tsc)) - return last_time; - - last_tsc = tsc; -#ifdef ZMQ_HAVE_WINDOWS - last_time = static_cast<uint64_t>((*my_get_tick_count64)()); -#else - last_time = now_us () / 1000; -#endif - return last_time; -} - -uint64_t zmq::clock_t::rdtsc () -{ -#if (defined _MSC_VER && (defined _M_IX86 || defined _M_X64)) - return __rdtsc (); -#elif (defined __GNUC__ && (defined __i386__ || defined __x86_64__)) - uint32_t low, high; - __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high)); - return (uint64_t) high << 32 | low; -#elif (defined __SUNPRO_CC && (__SUNPRO_CC >= 0x5100) && (defined __i386 || \ - defined __amd64 || defined __x86_64)) - union { - uint64_t u64val; - uint32_t u32val [2]; - } tsc; - asm("rdtsc" : "=a" (tsc.u32val [0]), "=d" (tsc.u32val [1])); - return tsc.u64val; -#elif defined(__s390__) - uint64_t tsc; - asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc"); - return(tsc); -#else - return 0; -#endif -} diff --git a/src/clock.hpp b/src/clock.hpp deleted file mode 100644 index e0d0fb1..0000000 --- a/src/clock.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_CLOCK_HPP_INCLUDED__ -#define __ZMQ_CLOCK_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - class clock_t - { - public: - - clock_t (); - ~clock_t (); - - // CPU's timestamp counter. Returns 0 if it's not available. - static uint64_t rdtsc (); - - // High precision timestamp. - static uint64_t now_us (); - - // Low precision timestamp. In tight loops generating it can be - // 10 to 100 times faster than the high precision timestamp. - uint64_t now_ms (); - - private: - - // TSC timestamp of when last time measurement was made. - uint64_t last_tsc; - - // Physical time corresponding to the TSC above (in milliseconds). - uint64_t last_time; - - clock_t (const clock_t&); - const clock_t &operator = (const clock_t&); - }; - -} - -#endif diff --git a/src/command.hpp b/src/command.hpp deleted file mode 100644 index fc0181b..0000000 --- a/src/command.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_COMMAND_HPP_INCLUDED__ -#define __ZMQ_COMMAND_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - class object_t; - class own_t; - struct i_engine; - class pipe_t; - class socket_base_t; - - // This structure defines the commands that can be sent between threads. - - struct command_t - { - // Object to process the command. - zmq::object_t *destination; - - enum type_t - { - stop, - plug, - own, - attach, - bind, - activate_read, - activate_write, - hiccup, - pipe_term, - pipe_term_ack, - term_req, - term, - term_ack, - reap, - reaped, - inproc_connected, - done - } type; - - union { - - // Sent to I/O thread to let it know that it should - // terminate itself. - struct { - } stop; - - // Sent to I/O object to make it register with its I/O thread. - struct { - } plug; - - // Sent to socket to let it know about the newly created object. - struct { - zmq::own_t *object; - } own; - - // Attach the engine to the session. If engine is NULL, it informs - // session that the connection have failed. - struct { - struct i_engine *engine; - } attach; - - // Sent from session to socket to establish pipe(s) between them. - // Caller have used inc_seqnum beforehand sending the command. - struct { - zmq::pipe_t *pipe; - } bind; - - // Sent by pipe writer to inform dormant pipe reader that there - // are messages in the pipe. - struct { - } activate_read; - - // Sent by pipe reader to inform pipe writer about how many - // messages it has read so far. - struct { - uint64_t msgs_read; - } activate_write; - - // Sent by pipe reader to writer after creating a new inpipe. - // The parameter is actually of type pipe_t::upipe_t, however, - // its definition is private so we'll have to do with void*. - struct { - void *pipe; - } hiccup; - - // Sent by pipe reader to pipe writer to ask it to terminate - // its end of the pipe. - struct { - } pipe_term; - - // Pipe writer acknowledges pipe_term command. - struct { - } pipe_term_ack; - - // Sent by I/O object ot the socket to request the shutdown of - // the I/O object. - struct { - zmq::own_t *object; - } term_req; - - // Sent by socket to I/O object to start its shutdown. - struct { - int linger; - } term; - - // Sent by I/O object to the socket to acknowledge it has - // shut down. - struct { - } term_ack; - - // Transfers the ownership of the closed socket - // to the reaper thread. - struct { - zmq::socket_base_t *socket; - } reap; - - // Closed socket notifies the reaper that it's already deallocated. - struct { - } reaped; - - // Sent by reaper thread to the term thread when all the sockets - // are successfully deallocated. - struct { - } done; - - } args; - }; - -} - -#endif diff --git a/src/config.hpp b/src/config.hpp deleted file mode 100644 index 6e5ef5a..0000000 --- a/src/config.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_CONFIG_HPP_INCLUDED__ -#define __ZMQ_CONFIG_HPP_INCLUDED__ - -namespace zmq -{ - - // Compile-time settings. - - enum - { - // Number of new messages in message pipe needed to trigger new memory - // allocation. Setting this parameter to 256 decreases the impact of - // memory allocation by approximately 99.6% - message_pipe_granularity = 256, - - // Commands in pipe per allocation event. - command_pipe_granularity = 16, - - // Determines how often does socket poll for new commands when it - // still has unprocessed messages to handle. Thus, if it is set to 100, - // socket will process 100 inbound messages before doing the poll. - // If there are no unprocessed messages available, poll is done - // immediately. Decreasing the value trades overall latency for more - // real-time behaviour (less latency peaks). - inbound_poll_rate = 100, - - // Maximal batching size for engines with receiving functionality. - // So, if there are 10 messages that fit into the batch size, all of - // them may be read by a single 'recv' system call, thus avoiding - // unnecessary network stack traversals. - in_batch_size = 8192, - - // Maximal batching size for engines with sending functionality. - // So, if there are 10 messages that fit into the batch size, all of - // them may be written by a single 'send' system call, thus avoiding - // unnecessary network stack traversals. - out_batch_size = 8192, - - // Maximal delta between high and low watermark. - max_wm_delta = 1024, - - // Maximum number of events the I/O thread can process in one go. - max_io_events = 256, - - // Maximal delay to process command in API thread (in CPU ticks). - // 3,000,000 ticks equals to 1 - 2 milliseconds on current CPUs. - // Note that delay is only applied when there is continuous stream of - // messages to process. If not so, commands are processed immediately. - max_command_delay = 3000000, - - // Low-precision clock precision in CPU ticks. 1ms. Value of 1000000 - // should be OK for CPU frequencies above 1GHz. If should work - // reasonably well for CPU frequencies above 500MHz. For lower CPU - // frequencies you may consider lowering this value to get best - // possible latencies. - clock_precision = 1000000, - - // Maximum transport data unit size for PGM (TPDU). - pgm_max_tpdu = 1500, - - // On some OSes the signaler has to be emulated using a TCP - // connection. In such cases following port is used. - signaler_port = 5905 - }; - -} - -#endif diff --git a/src/ctx.cpp b/src/ctx.cpp deleted file mode 100644 index a4e0c8b..0000000 --- a/src/ctx.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#endif - -#include <new> -#include <string.h> - -#include "ctx.hpp" -#include "socket_base.hpp" -#include "io_thread.hpp" -#include "reaper.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" - -#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe -#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef - -int clipped_maxsocket(int max_requested) -{ - if (max_requested >= zmq::poller_t::max_fds () && zmq::poller_t::max_fds () != -1) - max_requested = zmq::poller_t::max_fds () - 1; // -1 because we need room for the repear mailbox. - - return max_requested; -} - -zmq::ctx_t::ctx_t () : - tag (ZMQ_CTX_TAG_VALUE_GOOD), - starting (true), - terminating (false), - reaper (NULL), - slot_count (0), - slots (NULL), - max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)), - io_thread_count (ZMQ_IO_THREADS_DFLT), - ipv6 (false) -{ -#ifdef HAVE_FORK - pid = getpid(); -#endif -} - -bool zmq::ctx_t::check_tag () -{ - return tag == ZMQ_CTX_TAG_VALUE_GOOD; -} - -zmq::ctx_t::~ctx_t () -{ - // Check that there are no remaining sockets. - zmq_assert (sockets.empty ()); - - // Ask I/O threads to terminate. If stop signal wasn't sent to I/O - // thread subsequent invocation of destructor would hang-up. - for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) - io_threads [i]->stop (); - - // Wait till I/O threads actually terminate. - for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) - delete io_threads [i]; - - // Deallocate the reaper thread object. - delete reaper; - - // Deallocate the array of mailboxes. No special work is - // needed as mailboxes themselves were deallocated with their - // corresponding io_thread/socket objects. - free (slots); - - // Remove the tag, so that the object is considered dead. - tag = ZMQ_CTX_TAG_VALUE_BAD; -} - -int zmq::ctx_t::terminate () -{ - // Connect up any pending inproc connections, otherwise we will hang - pending_connections_t copy = pending_connections; - for (pending_connections_t::iterator p = copy.begin (); p != copy.end (); ++p) { - zmq::socket_base_t *s = create_socket (ZMQ_PAIR); - s->bind (p->first.c_str ()); - s->close (); - } - - slot_sync.lock (); - if (!starting) { - -#ifdef HAVE_FORK - if (pid != getpid()) - { - // we are a forked child process. Close all file descriptors - // inherited from the parent. - for (sockets_t::size_type i = 0; i != sockets.size (); i++) - { - sockets[i]->get_mailbox()->forked(); - } - - term_mailbox.forked(); - } -#endif - // Check whether termination was already underway, but interrupted and now - // restarted. - bool restarted = terminating; - terminating = true; - - // First attempt to terminate the context. - if (!restarted) { - - // First send stop command to sockets so that any blocking calls - // can be interrupted. If there are no sockets we can ask reaper - // thread to stop. - for (sockets_t::size_type i = 0; i != sockets.size (); i++) - sockets [i]->stop (); - if (sockets.empty ()) - reaper->stop (); - } - slot_sync.unlock(); - - // Wait till reaper thread closes all the sockets. - command_t cmd; - int rc = term_mailbox.recv (&cmd, -1); - if (rc == -1 && errno == EINTR) - return -1; - errno_assert (rc == 0); - zmq_assert (cmd.type == command_t::done); - slot_sync.lock (); - zmq_assert (sockets.empty ()); - } - slot_sync.unlock (); - - // Deallocate the resources. - delete this; - - return 0; -} - -int zmq::ctx_t::shutdown () -{ - slot_sync.lock (); - if (!starting && !terminating) { - terminating = true; - - // Send stop command to sockets so that any blocking calls - // can be interrupted. If there are no sockets we can ask reaper - // thread to stop. - for (sockets_t::size_type i = 0; i != sockets.size (); i++) - sockets [i]->stop (); - if (sockets.empty ()) - reaper->stop (); - } - slot_sync.unlock (); - - return 0; -} - -int zmq::ctx_t::set (int option_, int optval_) -{ - int rc = 0; - if (option_ == ZMQ_MAX_SOCKETS && optval_ >= 1 && optval_ == clipped_maxsocket (optval_)) { - opt_sync.lock (); - max_sockets = optval_; - opt_sync.unlock (); - } - else - if (option_ == ZMQ_IO_THREADS && optval_ >= 0) { - opt_sync.lock (); - io_thread_count = optval_; - opt_sync.unlock (); - } - else - if (option_ == ZMQ_IPV6 && optval_ >= 0) { - opt_sync.lock (); - ipv6 = (optval_ != 0); - opt_sync.unlock (); - } - else { - errno = EINVAL; - rc = -1; - } - return rc; -} - -int zmq::ctx_t::get (int option_) -{ - int rc = 0; - if (option_ == ZMQ_MAX_SOCKETS) - rc = max_sockets; - else - if (option_ == ZMQ_IO_THREADS) - rc = io_thread_count; - else - if (option_ == ZMQ_IPV6) - rc = ipv6; - else { - errno = EINVAL; - rc = -1; - } - return rc; -} - -zmq::socket_base_t *zmq::ctx_t::create_socket (int type_) -{ - slot_sync.lock (); - if (unlikely (starting)) { - - starting = false; - // Initialise the array of mailboxes. Additional three slots are for - // zmq_ctx_term thread and reaper thread. - opt_sync.lock (); - int mazmq = max_sockets; - int ios = io_thread_count; - opt_sync.unlock (); - slot_count = mazmq + ios + 2; - slots = (mailbox_t**) malloc (sizeof (mailbox_t*) * slot_count); - alloc_assert (slots); - - // Initialise the infrastructure for zmq_ctx_term thread. - slots [term_tid] = &term_mailbox; - - // Create the reaper thread. - reaper = new (std::nothrow) reaper_t (this, reaper_tid); - alloc_assert (reaper); - slots [reaper_tid] = reaper->get_mailbox (); - reaper->start (); - - // Create I/O thread objects and launch them. - for (int i = 2; i != ios + 2; i++) { - io_thread_t *io_thread = new (std::nothrow) io_thread_t (this, i); - alloc_assert (io_thread); - io_threads.push_back (io_thread); - slots [i] = io_thread->get_mailbox (); - io_thread->start (); - } - - // In the unused part of the slot array, create a list of empty slots. - for (int32_t i = (int32_t) slot_count - 1; - i >= (int32_t) ios + 2; i--) { - empty_slots.push_back (i); - slots [i] = NULL; - } - } - - // Once zmq_ctx_term() was called, we can't create new sockets. - if (terminating) { - slot_sync.unlock (); - errno = ETERM; - return NULL; - } - - // If max_sockets limit was reached, return error. - if (empty_slots.empty ()) { - slot_sync.unlock (); - errno = EMFILE; - return NULL; - } - - // Choose a slot for the socket. - uint32_t slot = empty_slots.back (); - empty_slots.pop_back (); - - // Generate new unique socket ID. - int sid = ((int) max_socket_id.add (1)) + 1; - - // Create the socket and register its mailbox. - socket_base_t *s = socket_base_t::create (type_, this, slot, sid); - if (!s) { - empty_slots.push_back (slot); - slot_sync.unlock (); - return NULL; - } - sockets.push_back (s); - slots [slot] = s->get_mailbox (); - - slot_sync.unlock (); - return s; -} - -void zmq::ctx_t::destroy_socket (class socket_base_t *socket_) -{ - slot_sync.lock (); - - // Free the associated thread slot. - uint32_t tid = socket_->get_tid (); - empty_slots.push_back (tid); - slots [tid] = NULL; - - // Remove the socket from the list of sockets. - sockets.erase (socket_); - - // If zmq_ctx_term() was already called and there are no more socket - // we can ask reaper thread to terminate. - if (terminating && sockets.empty ()) - reaper->stop (); - - slot_sync.unlock (); -} - -zmq::object_t *zmq::ctx_t::get_reaper () -{ - return reaper; -} - -void zmq::ctx_t::send_command (uint32_t tid_, const command_t &command_) -{ - slots [tid_]->send (command_); -} - -zmq::io_thread_t *zmq::ctx_t::choose_io_thread (uint64_t affinity_) -{ - if (io_threads.empty ()) - return NULL; - - // Find the I/O thread with minimum load. - int min_load = -1; - io_thread_t *selected_io_thread = NULL; - for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) { - if (!affinity_ || (affinity_ & (uint64_t (1) << i))) { - int load = io_threads [i]->get_load (); - if (selected_io_thread == NULL || load < min_load) { - min_load = load; - selected_io_thread = io_threads [i]; - } - } - } - return selected_io_thread; -} - -int zmq::ctx_t::register_endpoint (const char *addr_, endpoint_t &endpoint_) -{ - endpoints_sync.lock (); - - bool inserted = endpoints.insert (endpoints_t::value_type ( - std::string (addr_), endpoint_)).second; - - endpoints_sync.unlock (); - - if (!inserted) { - errno = EADDRINUSE; - return -1; - } - - return 0; -} - -void zmq::ctx_t::unregister_endpoints (socket_base_t *socket_) -{ - endpoints_sync.lock (); - - endpoints_t::iterator it = endpoints.begin (); - while (it != endpoints.end ()) { - if (it->second.socket == socket_) { - endpoints_t::iterator to_erase = it; - ++it; - endpoints.erase (to_erase); - continue; - } - ++it; - } - - endpoints_sync.unlock (); -} - -zmq::endpoint_t zmq::ctx_t::find_endpoint (const char *addr_) -{ - endpoints_sync.lock (); - - endpoints_t::iterator it = endpoints.find (addr_); - if (it == endpoints.end ()) { - endpoints_sync.unlock (); - errno = ECONNREFUSED; - endpoint_t empty = {NULL, options_t()}; - return empty; - } - endpoint_t endpoint = it->second; - - // Increment the command sequence number of the peer so that it won't - // get deallocated until "bind" command is issued by the caller. - // The subsequent 'bind' has to be called with inc_seqnum parameter - // set to false, so that the seqnum isn't incremented twice. - endpoint.socket->inc_seqnum (); - - endpoints_sync.unlock (); - return endpoint; -} - -void zmq::ctx_t::pend_connection (const char *addr_, pending_connection_t &pending_connection_) -{ - endpoints_sync.lock (); - - endpoints_t::iterator it = endpoints.find (addr_); - if (it == endpoints.end ()) - { - // Still no bind. - pending_connection_.endpoint.socket->inc_seqnum (); - pending_connections.insert (pending_connections_t::value_type (std::string (addr_), pending_connection_)); - } - else - { - // Bind has happened in the mean time, connect directly - connect_inproc_sockets(it->second.socket, it->second.options, pending_connection_, connect_side); - } - - endpoints_sync.unlock (); -} - -void zmq::ctx_t::connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_) -{ - endpoints_sync.lock (); - - std::pair<pending_connections_t::iterator, pending_connections_t::iterator> pending = pending_connections.equal_range(addr_); - - for (pending_connections_t::iterator p = pending.first; p != pending.second; ++p) - { - connect_inproc_sockets(bind_socket_, endpoints[addr_].options, p->second, bind_side); - } - - pending_connections.erase(pending.first, pending.second); - - endpoints_sync.unlock (); -} - -void zmq::ctx_t::connect_inproc_sockets(zmq::socket_base_t *bind_socket_, options_t& bind_options, pending_connection_t &pending_connection_, side side_) -{ - bind_socket_->inc_seqnum(); - pending_connection_.bind_pipe->set_tid(bind_socket_->get_tid()); - - if (side_ == bind_side) - { - command_t cmd; - cmd.type = command_t::bind; - cmd.args.bind.pipe = pending_connection_.bind_pipe; - bind_socket_->process_command(cmd); - bind_socket_->send_inproc_connected(pending_connection_.endpoint.socket); - } - else - { - pending_connection_.connect_pipe->send_bind(bind_socket_, pending_connection_.bind_pipe, false); - } - - int sndhwm = 0; - if (pending_connection_.endpoint.options.sndhwm != 0 && bind_options.rcvhwm != 0) - sndhwm = pending_connection_.endpoint.options.sndhwm + bind_options.rcvhwm; - int rcvhwm = 0; - if (pending_connection_.endpoint.options.rcvhwm != 0 && bind_options.sndhwm != 0) - rcvhwm = pending_connection_.endpoint.options.rcvhwm + bind_options.sndhwm; - - bool conflate = pending_connection_.endpoint.options.conflate && - (pending_connection_.endpoint.options.type == ZMQ_DEALER || - pending_connection_.endpoint.options.type == ZMQ_PULL || - pending_connection_.endpoint.options.type == ZMQ_PUSH || - pending_connection_.endpoint.options.type == ZMQ_PUB || - pending_connection_.endpoint.options.type == ZMQ_SUB); - - int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm}; - pending_connection_.connect_pipe->set_hwms(hwms [1], hwms [0]); - pending_connection_.bind_pipe->set_hwms(hwms [0], hwms [1]); - - if (bind_options.recv_identity) { - - msg_t id; - int rc = id.init_size (pending_connection_.endpoint.options.identity_size); - errno_assert (rc == 0); - memcpy (id.data (), pending_connection_.endpoint.options.identity, pending_connection_.endpoint.options.identity_size); - id.set_flags (msg_t::identity); - bool written = pending_connection_.connect_pipe->write (&id); - zmq_assert (written); - pending_connection_.connect_pipe->flush (); - } - if (pending_connection_.endpoint.options.recv_identity) { - msg_t id; - int rc = id.init_size (bind_options.identity_size); - errno_assert (rc == 0); - memcpy (id.data (), bind_options.identity, bind_options.identity_size); - id.set_flags (msg_t::identity); - bool written = pending_connection_.bind_pipe->write (&id); - zmq_assert (written); - pending_connection_.bind_pipe->flush (); - } -} - -// The last used socket ID, or 0 if no socket was used so far. Note that this -// is a global variable. Thus, even sockets created in different contexts have -// unique IDs. -zmq::atomic_counter_t zmq::ctx_t::max_socket_id; diff --git a/src/ctx.hpp b/src/ctx.hpp deleted file mode 100644 index 7473321..0000000 --- a/src/ctx.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_CTX_HPP_INCLUDED__ -#define __ZMQ_CTX_HPP_INCLUDED__ - -#include <map> -#include <vector> -#include <string> -#include <stdarg.h> - -#include "mailbox.hpp" -#include "array.hpp" -#include "config.hpp" -#include "mutex.hpp" -#include "stdint.hpp" -#include "options.hpp" -#include "atomic_counter.hpp" - -namespace zmq -{ - - class object_t; - class io_thread_t; - class socket_base_t; - class reaper_t; - class pipe_t; - - // Information associated with inproc endpoint. Note that endpoint options - // are registered as well so that the peer can access them without a need - // for synchronisation, handshaking or similar. - struct endpoint_t - { - socket_base_t *socket; - options_t options; - }; - - struct pending_connection_t - { - endpoint_t endpoint; - pipe_t* connect_pipe; - pipe_t* bind_pipe; - }; - - // Context object encapsulates all the global state associated with - // the library. - - class ctx_t - { - public: - - // Create the context object. - ctx_t (); - - // Returns false if object is not a context. - bool check_tag (); - - // This function is called when user invokes zmq_term. If there are - // no more sockets open it'll cause all the infrastructure to be shut - // down. If there are open sockets still, the deallocation happens - // after the last one is closed. - int terminate (); - - // This function starts the terminate process by unblocking any blocking - // operations currently in progress and stopping any more socket activity - // (except zmq_close). - // This function is non-blocking. - // terminate must still be called afterwards. - // This function is optional, terminate will unblock any current - // operations as well. - int shutdown(); - - // Set and get context properties. - int set (int option_, int optval_); - int get (int option_); - - // Create and destroy a socket. - zmq::socket_base_t *create_socket (int type_); - void destroy_socket (zmq::socket_base_t *socket_); - - // Send command to the destination thread. - void send_command (uint32_t tid_, const command_t &command_); - - // Returns the I/O thread that is the least busy at the moment. - // Affinity specifies which I/O threads are eligible (0 = all). - // Returns NULL if no I/O thread is available. - zmq::io_thread_t *choose_io_thread (uint64_t affinity_); - - // Returns reaper thread object. - zmq::object_t *get_reaper (); - - // Management of inproc endpoints. - int register_endpoint (const char *addr_, endpoint_t &endpoint_); - void unregister_endpoints (zmq::socket_base_t *socket_); - endpoint_t find_endpoint (const char *addr_); - void pend_connection (const char *addr_, pending_connection_t &pending_connection_); - void connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_); - - enum { - term_tid = 0, - reaper_tid = 1 - }; - - ~ctx_t (); - - private: - - - // Used to check whether the object is a context. - uint32_t tag; - - // Sockets belonging to this context. We need the list so that - // we can notify the sockets when zmq_term() is called. The sockets - // will return ETERM then. - typedef array_t <socket_base_t> sockets_t; - sockets_t sockets; - - // List of unused thread slots. - typedef std::vector <uint32_t> empty_slots_t; - empty_slots_t empty_slots; - - // If true, zmq_init has been called but no socket has been created - // yet. Launching of I/O threads is delayed. - bool starting; - - // If true, zmq_term was already called. - bool terminating; - - // Synchronisation of accesses to global slot-related data: - // sockets, empty_slots, terminating. It also synchronises - // access to zombie sockets as such (as opposed to slots) and provides - // a memory barrier to ensure that all CPU cores see the same data. - mutex_t slot_sync; - - // The reaper thread. - zmq::reaper_t *reaper; - - // I/O threads. - typedef std::vector <zmq::io_thread_t*> io_threads_t; - io_threads_t io_threads; - - // Array of pointers to mailboxes for both application and I/O threads. - uint32_t slot_count; - mailbox_t **slots; - - // Mailbox for zmq_term thread. - mailbox_t term_mailbox; - - // List of inproc endpoints within this context. - typedef std::map <std::string, endpoint_t> endpoints_t; - endpoints_t endpoints; - - // List of inproc connection endpoints pending a bind - typedef std::multimap <std::string, pending_connection_t> pending_connections_t; - pending_connections_t pending_connections; - - // Synchronisation of access to the list of inproc endpoints. - mutex_t endpoints_sync; - - // Maximum socket ID. - static atomic_counter_t max_socket_id; - - // Maximum number of sockets that can be opened at the same time. - int max_sockets; - - // Number of I/O threads to launch. - int io_thread_count; - - // Is IPv6 enabled on this context? - bool ipv6; - - // Synchronisation of access to context options. - mutex_t opt_sync; - - ctx_t (const ctx_t&); - const ctx_t &operator = (const ctx_t&); - -#ifdef HAVE_FORK - // the process that created this context. Used to detect forking. - pid_t pid; -#endif - enum side { connect_side, bind_side }; - void connect_inproc_sockets(zmq::socket_base_t *bind_socket_, options_t& bind_options, pending_connection_t &pending_connection_, side side_); - }; - -} - -#endif diff --git a/src/curve_client.cpp b/src/curve_client.cpp deleted file mode 100644 index f832466..0000000 --- a/src/curve_client.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#ifdef HAVE_LIBSODIUM - -#include <sodium.h> - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "msg.hpp" -#include "session_base.hpp" -#include "err.hpp" -#include "curve_client.hpp" -#include "wire.hpp" - -zmq::curve_client_t::curve_client_t (const options_t &options_) : - mechanism_t (options_), - state (send_hello) -{ - memcpy (public_key, options_.curve_public_key, crypto_box_PUBLICKEYBYTES); - memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); - memcpy (server_key, options_.curve_server_key, crypto_box_PUBLICKEYBYTES); - - // Generate short-term key pair - const int rc = crypto_box_keypair (cn_public, cn_secret); - zmq_assert (rc == 0); -} - -zmq::curve_client_t::~curve_client_t () -{ -} - -int zmq::curve_client_t::next_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case send_hello: - rc = produce_hello (msg_); - if (rc == 0) - state = expect_welcome; - break; - case send_initiate: - rc = produce_initiate (msg_); - if (rc == 0) - state = expect_ready; - break; - default: - errno = EAGAIN; - rc = -1; - } - return rc; -} - -int zmq::curve_client_t::process_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case expect_welcome: - rc = process_welcome (msg_); - if (rc == 0) - state = send_initiate; - break; - case expect_ready: - rc = process_ready (msg_); - if (rc == 0) - state = connected; - break; - default: - errno = EPROTO; - rc = -1; - break; - } - if (rc == 0) { - rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - } - return rc; -} - -int zmq::curve_client_t::encode (msg_t *msg_) -{ - zmq_assert (state == connected); - - uint8_t flags = 0; - if (msg_->flags () & msg_t::more) - flags |= 0x01; - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGEC", 16); - memcpy (message_nonce + 16, &cn_nonce, 8); - - const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size (); - - uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (mlen)); - alloc_assert (message_plaintext); - - memset (message_plaintext, 0, crypto_box_ZEROBYTES); - message_plaintext [crypto_box_ZEROBYTES] = flags; - memcpy (message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->data (), msg_->size ()); - - uint8_t *message_box = static_cast <uint8_t *> (malloc (mlen)); - alloc_assert (message_box); - - int rc = crypto_box_afternm (message_box, message_plaintext, - mlen, message_nonce, cn_precom); - zmq_assert (rc == 0); - - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); - zmq_assert (rc == 0); - - uint8_t *message = static_cast <uint8_t *> (msg_->data ()); - - memcpy (message, "\x07MESSAGE", 8); - memcpy (message + 8, &cn_nonce, 8); - memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - - free (message_plaintext); - free (message_box); - - cn_nonce++; - - return 0; -} - -int zmq::curve_client_t::decode (msg_t *msg_) -{ - zmq_assert (state == connected); - - if (msg_->size () < 33) { - errno = EPROTO; - return -1; - } - - const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (message, "\x07MESSAGE", 8)) { - errno = EPROTO; - return -1; - } - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGES", 16); - memcpy (message_nonce + 16, message + 8, 8); - - const size_t clen = crypto_box_BOXZEROBYTES + (msg_->size () - 16); - - uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (clen)); - alloc_assert (message_plaintext); - - uint8_t *message_box = static_cast <uint8_t *> (malloc (clen)); - alloc_assert (message_box); - - memset (message_box, 0, crypto_box_BOXZEROBYTES); - memcpy (message_box + crypto_box_BOXZEROBYTES, - message + 16, msg_->size () - 16); - - int rc = crypto_box_open_afternm (message_plaintext, message_box, - clen, message_nonce, cn_precom); - if (rc == 0) { - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); - zmq_assert (rc == 0); - - const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; - if (flags & 0x01) - msg_->set_flags (msg_t::more); - - memcpy (msg_->data (), - message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->size ()); - } - else - errno = EPROTO; - - free (message_plaintext); - free (message_box); - - return rc; -} - -bool zmq::curve_client_t::is_handshake_complete () const -{ - return state == connected; -} - -int zmq::curve_client_t::produce_hello (msg_t *msg_) -{ - uint8_t hello_nonce [crypto_box_NONCEBYTES]; - uint8_t hello_plaintext [crypto_box_ZEROBYTES + 64]; - uint8_t hello_box [crypto_box_BOXZEROBYTES + 80]; - - // Prepare the full nonce - memcpy (hello_nonce, "CurveZMQHELLO---", 16); - memcpy (hello_nonce + 16, &cn_nonce, 8); - - // Create Box [64 * %x0](C'->S) - memset (hello_plaintext, 0, sizeof hello_plaintext); - - int rc = crypto_box (hello_box, hello_plaintext, - sizeof hello_plaintext, - hello_nonce, server_key, cn_secret); - zmq_assert (rc == 0); - - rc = msg_->init_size (200); - errno_assert (rc == 0); - uint8_t *hello = static_cast <uint8_t *> (msg_->data ()); - - memcpy (hello, "\x05HELLO", 6); - // CurveZMQ major and minor version numbers - memcpy (hello + 6, "\1\0", 2); - // Anti-amplification padding - memset (hello + 8, 0, 72); - // Client public connection key - memcpy (hello + 80, cn_public, crypto_box_PUBLICKEYBYTES); - // Short nonce, prefixed by "CurveZMQHELLO---" - memcpy (hello + 112, hello_nonce + 16, 8); - // Signature, Box [64 * %x0](C'->S) - memcpy (hello + 120, hello_box + crypto_box_BOXZEROBYTES, 80); - - cn_nonce++; - - return 0; -} - -int zmq::curve_client_t::process_welcome (msg_t *msg_) -{ - if (msg_->size () != 168) { - errno = EPROTO; - return -1; - } - - const uint8_t * welcome = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (welcome, "\x07WELCOME", 8)) { - errno = EPROTO; - return -1; - } - - uint8_t welcome_nonce [crypto_box_NONCEBYTES]; - uint8_t welcome_plaintext [crypto_box_ZEROBYTES + 128]; - uint8_t welcome_box [crypto_box_BOXZEROBYTES + 144]; - - // Open Box [S' + cookie](C'->S) - memset (welcome_box, 0, crypto_box_BOXZEROBYTES); - memcpy (welcome_box + crypto_box_BOXZEROBYTES, welcome + 24, 144); - - memcpy (welcome_nonce, "WELCOME-", 8); - memcpy (welcome_nonce + 8, welcome + 8, 16); - - int rc = crypto_box_open (welcome_plaintext, welcome_box, - sizeof welcome_box, - welcome_nonce, server_key, cn_secret); - if (rc != 0) { - errno = EPROTO; - return -1; - } - - memcpy (cn_server, welcome_plaintext + crypto_box_ZEROBYTES, 32); - memcpy (cn_cookie, welcome_plaintext + crypto_box_ZEROBYTES + 32, 16 + 80); - - // Message independent precomputation - rc = crypto_box_beforenm (cn_precom, cn_server, cn_secret); - zmq_assert (rc == 0); - - return 0; -} - -int zmq::curve_client_t::produce_initiate (msg_t *msg_) -{ - uint8_t vouch_nonce [crypto_box_NONCEBYTES]; - uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64]; - uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80]; - - // Create vouch = Box [C',S](C->S') - memset (vouch_plaintext, 0, crypto_box_ZEROBYTES); - memcpy (vouch_plaintext + crypto_box_ZEROBYTES, cn_public, 32); - memcpy (vouch_plaintext + crypto_box_ZEROBYTES + 32, server_key, 32); - - memcpy (vouch_nonce, "VOUCH---", 8); - randombytes (vouch_nonce + 8, 16); - - int rc = crypto_box (vouch_box, vouch_plaintext, - sizeof vouch_plaintext, - vouch_nonce, cn_server, secret_key); - zmq_assert (rc == 0); - - // Assume here that metadata is limited to 256 bytes - uint8_t initiate_nonce [crypto_box_NONCEBYTES]; - uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256]; - uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256]; - - // Create Box [C + vouch + metadata](C'->S') - memset (initiate_plaintext, 0, crypto_box_ZEROBYTES); - memcpy (initiate_plaintext + crypto_box_ZEROBYTES, - public_key, 32); - memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 32, - vouch_nonce + 8, 16); - memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 48, - vouch_box + crypto_box_BOXZEROBYTES, 80); - - // Metadata starts after vouch - uint8_t *ptr = initiate_plaintext + crypto_box_ZEROBYTES + 128; - - // Add socket type property - const char *socket_type = socket_type_string (options.type); - ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type)); - - // Add identity property - if (options.type == ZMQ_REQ - || options.type == ZMQ_DEALER - || options.type == ZMQ_ROUTER) - ptr += add_property (ptr, "Identity", - options.identity, options.identity_size); - - const size_t mlen = ptr - initiate_plaintext; - - memcpy (initiate_nonce, "CurveZMQINITIATE", 16); - memcpy (initiate_nonce + 16, &cn_nonce, 8); - - rc = crypto_box (initiate_box, initiate_plaintext, - mlen, initiate_nonce, cn_server, cn_secret); - zmq_assert (rc == 0); - - rc = msg_->init_size (113 + mlen - crypto_box_BOXZEROBYTES); - errno_assert (rc == 0); - - uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); - - memcpy (initiate, "\x08INITIATE", 9); - // Cookie provided by the server in the WELCOME command - memcpy (initiate + 9, cn_cookie, 96); - // Short nonce, prefixed by "CurveZMQINITIATE" - memcpy (initiate + 105, &cn_nonce, 8); - // Box [C + vouch + metadata](C'->S') - memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - cn_nonce++; - - return 0; -} - -int zmq::curve_client_t::process_ready (msg_t *msg_) -{ - if (msg_->size () < 30) { - errno = EPROTO; - return -1; - } - - const uint8_t *ready = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (ready, "\x05READY", 6)) { - errno = EPROTO; - return -1; - } - - const size_t clen = (msg_->size () - 14) + crypto_box_BOXZEROBYTES; - - uint8_t ready_nonce [crypto_box_NONCEBYTES]; - uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256]; - uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256]; - - memset (ready_box, 0, crypto_box_BOXZEROBYTES); - memcpy (ready_box + crypto_box_BOXZEROBYTES, - ready + 14, clen - crypto_box_BOXZEROBYTES); - - memcpy (ready_nonce, "CurveZMQREADY---", 16); - memcpy (ready_nonce + 16, ready + 6, 8); - - int rc = crypto_box_open_afternm (ready_plaintext, ready_box, - clen, ready_nonce, cn_precom); - - if (rc != 0) { - errno = EPROTO; - return -1; - } - - rc = parse_metadata (ready_plaintext + crypto_box_ZEROBYTES, - clen - crypto_box_ZEROBYTES); - return rc; -} - -#endif diff --git a/src/curve_client.hpp b/src/curve_client.hpp deleted file mode 100644 index c1569d2..0000000 --- a/src/curve_client.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_CURVE_CLIENT_HPP_INCLUDED__ -#define __ZMQ_CURVE_CLIENT_HPP_INCLUDED__ - -#include "platform.hpp" - -#ifdef HAVE_LIBSODIUM -#include <sodium.h> - -#if crypto_box_NONCEBYTES != 24 \ -|| crypto_box_PUBLICKEYBYTES != 32 \ -|| crypto_box_SECRETKEYBYTES != 32 \ -|| crypto_box_ZEROBYTES != 32 \ -|| crypto_box_BOXZEROBYTES != 16 -#error "libsodium not built properly" -#endif - -#include "mechanism.hpp" -#include "options.hpp" - -namespace zmq -{ - - class msg_t; - class session_base_t; - - class curve_client_t : public mechanism_t - { - public: - - curve_client_t (const options_t &options_); - virtual ~curve_client_t (); - - // mechanism implementation - virtual int next_handshake_command (msg_t *msg_); - virtual int process_handshake_command (msg_t *msg_); - virtual int encode (msg_t *msg_); - virtual int decode (msg_t *msg_); - virtual bool is_handshake_complete () const; - - private: - - enum state_t { - send_hello, - expect_welcome, - send_initiate, - expect_ready, - connected - }; - - // Current FSM state - state_t state; - - // Our public key (C) - uint8_t public_key [crypto_box_PUBLICKEYBYTES]; - - // Our secret key (c) - uint8_t secret_key [crypto_box_SECRETKEYBYTES]; - - // Our short-term public key (C') - uint8_t cn_public [crypto_box_PUBLICKEYBYTES]; - - // Our short-term secret key (c') - uint8_t cn_secret [crypto_box_SECRETKEYBYTES]; - - // Server's public key (S) - uint8_t server_key [crypto_box_PUBLICKEYBYTES]; - - // Server's short-term public key (S') - uint8_t cn_server [crypto_box_PUBLICKEYBYTES]; - - // Cookie received from server - uint8_t cn_cookie [16 + 80]; - - // Intermediary buffer used to seepd up boxing and unboxing. - uint8_t cn_precom [crypto_box_BEFORENMBYTES]; - - // Nonce - uint64_t cn_nonce; - - int produce_hello (msg_t *msg_); - int process_welcome (msg_t *msg_); - int produce_initiate (msg_t *msg_); - int process_ready (msg_t *msg_); - }; - -} - -#endif - -#endif diff --git a/src/curve_server.cpp b/src/curve_server.cpp deleted file mode 100644 index a324441..0000000 --- a/src/curve_server.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#ifdef HAVE_LIBSODIUM -#include <sodium.h> - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "msg.hpp" -#include "session_base.hpp" -#include "err.hpp" -#include "curve_server.hpp" -#include "wire.hpp" - -zmq::curve_server_t::curve_server_t (session_base_t *session_, - const std::string &peer_address_, - const options_t &options_) : - mechanism_t (options_), - session (session_), - peer_address (peer_address_), - state (expect_hello), - expecting_zap_reply (false), - cn_nonce (1) -{ - // Fetch our secret key from socket options - memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); - - // Generate short-term key pair - const int rc = crypto_box_keypair (cn_public, cn_secret); - zmq_assert (rc == 0); -} - -zmq::curve_server_t::~curve_server_t () -{ -} - -int zmq::curve_server_t::next_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case send_welcome: - rc = produce_welcome (msg_); - if (rc == 0) - state = expect_initiate; - break; - case send_ready: - rc = produce_ready (msg_); - if (rc == 0) - state = connected; - break; - default: - errno = EAGAIN; - rc = -1; - break; - } - return rc; -} - -int zmq::curve_server_t::process_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case expect_hello: - rc = process_hello (msg_); - if (rc == 0) - state = send_welcome; - break; - case expect_initiate: - rc = process_initiate (msg_); - if (rc == 0) - state = expecting_zap_reply? expect_zap_reply: send_ready; - break; - default: - errno = EPROTO; - rc = -1; - break; - } - if (rc == 0) { - rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - } - return rc; -} - -int zmq::curve_server_t::encode (msg_t *msg_) -{ - zmq_assert (state == connected); - - const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size (); - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGES", 16); - memcpy (message_nonce + 16, &cn_nonce, 8); - - uint8_t flags = 0; - if (msg_->flags () & msg_t::more) - flags |= 0x01; - - uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (mlen)); - alloc_assert (message_plaintext); - - memset (message_plaintext, 0, crypto_box_ZEROBYTES); - message_plaintext [crypto_box_ZEROBYTES] = flags; - memcpy (message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->data (), msg_->size ()); - - uint8_t *message_box = static_cast <uint8_t *> (malloc (mlen)); - alloc_assert (message_box); - - int rc = crypto_box_afternm (message_box, message_plaintext, - mlen, message_nonce, cn_precom); - zmq_assert (rc == 0); - - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); - zmq_assert (rc == 0); - - uint8_t *message = static_cast <uint8_t *> (msg_->data ()); - - memcpy (message, "\x07MESSAGE", 8); - memcpy (message + 8, &cn_nonce, 8); - memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - - free (message_plaintext); - free (message_box); - - cn_nonce++; - - return 0; -} - -int zmq::curve_server_t::decode (msg_t *msg_) -{ - zmq_assert (state == connected); - - if (msg_->size () < 33) { - errno = EPROTO; - return -1; - } - - const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (message, "\x07MESSAGE", 8)) { - errno = EPROTO; - return -1; - } - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGEC", 16); - memcpy (message_nonce + 16, message + 8, 8); - - const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16; - - uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (clen)); - alloc_assert (message_plaintext); - - uint8_t *message_box = static_cast <uint8_t *> (malloc (clen)); - alloc_assert (message_box); - - memset (message_box, 0, crypto_box_BOXZEROBYTES); - memcpy (message_box + crypto_box_BOXZEROBYTES, - message + 16, msg_->size () - 16); - - int rc = crypto_box_open_afternm (message_plaintext, message_box, - clen, message_nonce, cn_precom); - if (rc == 0) { - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); - zmq_assert (rc == 0); - - const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; - if (flags & 0x01) - msg_->set_flags (msg_t::more); - - memcpy (msg_->data (), - message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->size ()); - } - else - errno = EPROTO; - - free (message_plaintext); - free (message_box); - - return rc; -} - -int zmq::curve_server_t::zap_msg_available () -{ - if (state != expect_zap_reply) { - errno = EFSM; - return -1; - } - const int rc = receive_and_process_zap_reply (); - if (rc == 0) - state = send_ready; - return rc; -} - -bool zmq::curve_server_t::is_handshake_complete () const -{ - return state == connected; -} - -int zmq::curve_server_t::process_hello (msg_t *msg_) -{ - if (msg_->size () != 200) { - errno = EPROTO; - return -1; - } - - const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (hello, "\x05HELLO", 6)) { - errno = EPROTO; - return -1; - } - - const uint8_t major = hello [6]; - const uint8_t minor = hello [7]; - - if (major != 1 || minor != 0) { - errno = EPROTO; - return -1; - } - - // Save client's short-term public key (C') - memcpy (cn_client, hello + 80, 32); - - uint8_t hello_nonce [crypto_box_NONCEBYTES]; - uint8_t hello_plaintext [crypto_box_ZEROBYTES + 64]; - uint8_t hello_box [crypto_box_BOXZEROBYTES + 80]; - - memcpy (hello_nonce, "CurveZMQHELLO---", 16); - memcpy (hello_nonce + 16, hello + 112, 8); - - memset (hello_box, 0, crypto_box_BOXZEROBYTES); - memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80); - - // Open Box [64 * %x0](C'->S) - int rc = crypto_box_open (hello_plaintext, hello_box, - sizeof hello_box, - hello_nonce, cn_client, secret_key); - if (rc != 0) { - errno = EPROTO; - return -1; - } - - return rc; -} - -int zmq::curve_server_t::produce_welcome (msg_t *msg_) -{ - uint8_t cookie_nonce [crypto_secretbox_NONCEBYTES]; - uint8_t cookie_plaintext [crypto_secretbox_ZEROBYTES + 64]; - uint8_t cookie_ciphertext [crypto_secretbox_BOXZEROBYTES + 80]; - - // Create full nonce for encryption - // 8-byte prefix plus 16-byte random nonce - memcpy (cookie_nonce, "COOKIE--", 8); - randombytes (cookie_nonce + 8, 16); - - // Generate cookie = Box [C' + s'](t) - memset (cookie_plaintext, 0, crypto_secretbox_ZEROBYTES); - memcpy (cookie_plaintext + crypto_secretbox_ZEROBYTES, - cn_client, 32); - memcpy (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, - cn_secret, 32); - - // Generate fresh cookie key - randombytes (cookie_key, crypto_secretbox_KEYBYTES); - - // Encrypt using symmetric cookie key - int rc = crypto_secretbox (cookie_ciphertext, cookie_plaintext, - sizeof cookie_plaintext, - cookie_nonce, cookie_key); - zmq_assert (rc == 0); - - uint8_t welcome_nonce [crypto_box_NONCEBYTES]; - uint8_t welcome_plaintext [crypto_box_ZEROBYTES + 128]; - uint8_t welcome_ciphertext [crypto_box_BOXZEROBYTES + 144]; - - // Create full nonce for encryption - // 8-byte prefix plus 16-byte random nonce - memcpy (welcome_nonce, "WELCOME-", 8); - randombytes (welcome_nonce + 8, crypto_box_NONCEBYTES - 8); - - // Create 144-byte Box [S' + cookie](S->C') - memset (welcome_plaintext, 0, crypto_box_ZEROBYTES); - memcpy (welcome_plaintext + crypto_box_ZEROBYTES, cn_public, 32); - memcpy (welcome_plaintext + crypto_box_ZEROBYTES + 32, - cookie_nonce + 8, 16); - memcpy (welcome_plaintext + crypto_box_ZEROBYTES + 48, - cookie_ciphertext + crypto_secretbox_BOXZEROBYTES, 80); - - rc = crypto_box (welcome_ciphertext, welcome_plaintext, - sizeof welcome_plaintext, - welcome_nonce, cn_client, secret_key); - zmq_assert (rc == 0); - - rc = msg_->init_size (168); - errno_assert (rc == 0); - - uint8_t * const welcome = static_cast <uint8_t *> (msg_->data ()); - memcpy (welcome, "\x07WELCOME", 8); - memcpy (welcome + 8, welcome_nonce + 8, 16); - memcpy (welcome + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144); - - return 0; -} - -int zmq::curve_server_t::process_initiate (msg_t *msg_) -{ - if (msg_->size () < 257) { - errno = EPROTO; - return -1; - } - - const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); - if (memcmp (initiate, "\x08INITIATE", 9)) { - errno = EPROTO; - return -1; - } - - uint8_t cookie_nonce [crypto_secretbox_NONCEBYTES]; - uint8_t cookie_plaintext [crypto_secretbox_ZEROBYTES + 64]; - uint8_t cookie_box [crypto_secretbox_BOXZEROBYTES + 80]; - - // Open Box [C' + s'](t) - memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES); - memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80); - - memcpy (cookie_nonce, "COOKIE--", 8); - memcpy (cookie_nonce + 8, initiate + 9, 16); - - int rc = crypto_secretbox_open (cookie_plaintext, cookie_box, - sizeof cookie_box, - cookie_nonce, cookie_key); - if (rc != 0) { - errno = EPROTO; - return -1; - } - - // Check cookie plain text is as expected [C' + s'] - if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32) - || memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) { - errno = EPROTO; - return -1; - } - - const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES; - - uint8_t initiate_nonce [crypto_box_NONCEBYTES]; - uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256]; - uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256]; - - // Open Box [C + vouch + metadata](C'->S') - memset (initiate_box, 0, crypto_box_BOXZEROBYTES); - memcpy (initiate_box + crypto_box_BOXZEROBYTES, - initiate + 113, clen - crypto_box_BOXZEROBYTES); - - memcpy (initiate_nonce, "CurveZMQINITIATE", 16); - memcpy (initiate_nonce + 16, initiate + 105, 8); - - rc = crypto_box_open (initiate_plaintext, initiate_box, - clen, initiate_nonce, cn_client, cn_secret); - if (rc != 0) { - errno = EPROTO; - return -1; - } - - const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES; - - uint8_t vouch_nonce [crypto_box_NONCEBYTES]; - uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64]; - uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80]; - - // Open Box Box [C',S](C->S') and check contents - memset (vouch_box, 0, crypto_box_BOXZEROBYTES); - memcpy (vouch_box + crypto_box_BOXZEROBYTES, - initiate_plaintext + crypto_box_ZEROBYTES + 48, 80); - - memcpy (vouch_nonce, "VOUCH---", 8); - memcpy (vouch_nonce + 8, - initiate_plaintext + crypto_box_ZEROBYTES + 32, 16); - - rc = crypto_box_open (vouch_plaintext, vouch_box, - sizeof vouch_box, - vouch_nonce, client_key, cn_secret); - if (rc != 0) { - errno = EPROTO; - return -1; - } - - // What we decrypted must be the client's short-term public key - if (memcmp (vouch_plaintext + crypto_box_ZEROBYTES, cn_client, 32)) { - errno = EPROTO; - return -1; - } - - // Precompute connection secret from client key - rc = crypto_box_beforenm (cn_precom, cn_client, cn_secret); - zmq_assert (rc == 0); - - // Use ZAP protocol (RFC 27) to authenticate the user. - rc = session->zap_connect (); - if (rc == 0) { - send_zap_request (client_key); - rc = receive_and_process_zap_reply (); - if (rc != 0) { - if (errno != EAGAIN) - return -1; - expecting_zap_reply = true; - } - } - - return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128, - clen - crypto_box_ZEROBYTES - 128); -} - -int zmq::curve_server_t::produce_ready (msg_t *msg_) -{ - uint8_t ready_nonce [crypto_box_NONCEBYTES]; - uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256]; - uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256]; - - // Create Box [metadata](S'->C') - memset (ready_plaintext, 0, crypto_box_ZEROBYTES); - uint8_t *ptr = ready_plaintext + crypto_box_ZEROBYTES; - - // Add socket type property - const char *socket_type = socket_type_string (options.type); - ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type)); - - // Add identity property - if (options.type == ZMQ_REQ - || options.type == ZMQ_DEALER - || options.type == ZMQ_ROUTER) - ptr += add_property (ptr, "Identity", - options.identity, options.identity_size); - - const size_t mlen = ptr - ready_plaintext; - - memcpy (ready_nonce, "CurveZMQREADY---", 16); - memcpy (ready_nonce + 16, &cn_nonce, 8); - - int rc = crypto_box_afternm (ready_box, ready_plaintext, - mlen, ready_nonce, cn_precom); - zmq_assert (rc == 0); - - rc = msg_->init_size (14 + mlen - crypto_box_BOXZEROBYTES); - errno_assert (rc == 0); - - uint8_t *ready = static_cast <uint8_t *> (msg_->data ()); - - memcpy (ready, "\x05READY", 6); - // Short nonce, prefixed by "CurveZMQREADY---" - memcpy (ready + 6, &cn_nonce, 8); - // Box [metadata](S'->C') - memcpy (ready + 14, ready_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - - cn_nonce++; - - return 0; -} - -void zmq::curve_server_t::send_zap_request (const uint8_t *key) -{ - int rc; - msg_t msg; - - // Address delimiter frame - rc = msg.init (); - errno_assert (rc == 0); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Version frame - rc = msg.init_size (3); - errno_assert (rc == 0); - memcpy (msg.data (), "1.0", 3); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Request ID frame - rc = msg.init_size (1); - errno_assert (rc == 0); - memcpy (msg.data (), "1", 1); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Domain frame - rc = msg.init_size (options.zap_domain.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Address frame - rc = msg.init_size (peer_address.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), peer_address.c_str (), peer_address.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Identity frame - rc = msg.init_size (options.identity_size); - errno_assert (rc == 0); - memcpy (msg.data (), options.identity, options.identity_size); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Mechanism frame - rc = msg.init_size (5); - errno_assert (rc == 0); - memcpy (msg.data (), "CURVE", 5); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Credentials frame - rc = msg.init_size (crypto_box_PUBLICKEYBYTES); - errno_assert (rc == 0); - memcpy (msg.data (), key, crypto_box_PUBLICKEYBYTES); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); -} - -int zmq::curve_server_t::receive_and_process_zap_reply () -{ - int rc = 0; - msg_t msg [7]; // ZAP reply consists of 7 frames - - // Initialize all reply frames - for (int i = 0; i < 7; i++) { - rc = msg [i].init (); - errno_assert (rc == 0); - } - - for (int i = 0; i < 7; i++) { - rc = session->read_zap_msg (&msg [i]); - if (rc == -1) - break; - if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) { - errno = EPROTO; - rc = -1; - break; - } - } - - if (rc != 0) - goto error; - - // Address delimiter frame - if (msg [0].size () > 0) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Version frame - if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Request id frame - if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Status code frame - if (msg [3].size () != 3 || memcmp (msg [3].data (), "200", 3)) { - rc = -1; - errno = EACCES; - goto error; - } - - // Process metadata frame - rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()), - msg [6].size ()); - -error: - for (int i = 0; i < 7; i++) { - const int rc2 = msg [i].close (); - errno_assert (rc2 == 0); - } - - return rc; -} - -#endif diff --git a/src/curve_server.hpp b/src/curve_server.hpp deleted file mode 100644 index c165b54..0000000 --- a/src/curve_server.hpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_CURVE_SERVER_HPP_INCLUDED__ -#define __ZMQ_CURVE_SERVER_HPP_INCLUDED__ - -#include "platform.hpp" - -#ifdef HAVE_LIBSODIUM -#include <sodium.h> - -#if crypto_box_NONCEBYTES != 24 \ -|| crypto_box_PUBLICKEYBYTES != 32 \ -|| crypto_box_SECRETKEYBYTES != 32 \ -|| crypto_box_ZEROBYTES != 32 \ -|| crypto_box_BOXZEROBYTES != 16 \ -|| crypto_secretbox_NONCEBYTES != 24 \ -|| crypto_secretbox_ZEROBYTES != 32 \ -|| crypto_secretbox_BOXZEROBYTES != 16 -#error "libsodium not built properly" -#endif - -#include "mechanism.hpp" -#include "options.hpp" - -namespace zmq -{ - - class msg_t; - class session_base_t; - - class curve_server_t : public mechanism_t - { - public: - - curve_server_t (session_base_t *session_, - const std::string &peer_address_, - const options_t &options_); - virtual ~curve_server_t (); - - // mechanism implementation - virtual int next_handshake_command (msg_t *msg_); - virtual int process_handshake_command (msg_t *msg_); - virtual int encode (msg_t *msg_); - virtual int decode (msg_t *msg_); - virtual int zap_msg_available (); - virtual bool is_handshake_complete () const; - - private: - - enum state_t { - expect_hello, - send_welcome, - expect_initiate, - expect_zap_reply, - send_ready, - connected - }; - - session_base_t * const session; - - const std::string peer_address; - - // Current FSM state - state_t state; - - // True iff we are awaiting reply from ZAP handler. - bool expecting_zap_reply; - - uint64_t cn_nonce; - - // Our secret key (s) - uint8_t secret_key [crypto_box_SECRETKEYBYTES]; - - // Our short-term public key (S') - uint8_t cn_public [crypto_box_PUBLICKEYBYTES]; - - // Our short-term secret key (s') - uint8_t cn_secret [crypto_box_SECRETKEYBYTES]; - - // Client's short-term public key (C') - uint8_t cn_client [crypto_box_PUBLICKEYBYTES]; - - // Key used to produce cookie - uint8_t cookie_key [crypto_secretbox_KEYBYTES]; - - // Intermediary buffer used to speed up boxing and unboxing. - uint8_t cn_precom [crypto_box_BEFORENMBYTES]; - - int process_hello (msg_t *msg_); - int produce_welcome (msg_t *msg_); - int process_initiate (msg_t *msg_); - int produce_ready (msg_t *msg_); - - void send_zap_request (const uint8_t *key); - int receive_and_process_zap_reply (); - }; - -} - -#endif - -#endif - diff --git a/src/dbuffer.hpp b/src/dbuffer.hpp deleted file mode 100644 index 7929304..0000000 --- a/src/dbuffer.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_DBUFFER_HPP_INCLUDED__ -#define __ZMQ_DBUFFER_HPP_INCLUDED__ - -#include <stdlib.h> -#include <stddef.h> -#include <algorithm> - -#include "mutex.hpp" -#include "msg.hpp" - -namespace zmq -{ - - // dbuffer is a single-producer single-consumer double-buffer - // implementation. - // - // The producer writes to a back buffer and then tries to swap - // pointers between the back and front buffers. If it fails, - // due to the consumer reading from the front buffer, it just - // gives up, which is ok since writes are many and redundant. - // - // The reader simply reads from the front buffer. - // - // has_msg keeps track of whether there has been a not yet read - // value written, it is used by ypipe_conflate to mimic ypipe - // functionality regarding a reader being asleep - - template <typename T> class dbuffer_t; - - template <> class dbuffer_t<msg_t> - { - public: - - inline dbuffer_t () - : back (&storage[0]) - , front (&storage[1]) - , has_msg (false) - { - back->init (); - front->init (); - } - - inline ~dbuffer_t() - { - back->close (); - front->close (); - } - - inline void write (const msg_t &value_) - { - msg_t& xvalue = const_cast<msg_t&>(value_); - - zmq_assert (xvalue.check ()); - back->move (xvalue); // cannot just overwrite, might leak - - zmq_assert (back->check ()); - - if (sync.try_lock ()) - { - std::swap (back, front); - has_msg = true; - - sync.unlock (); - } - } - - inline bool read (msg_t *value_) - { - if (!value_) - return false; - - { - scoped_lock_t lock (sync); - if (!has_msg) - return false; - - zmq_assert (front->check ()); - - *value_ = *front; - front->init (); // avoid double free - - has_msg = false; - return true; - } - } - - - inline bool check_read () - { - scoped_lock_t lock (sync); - - return has_msg; - } - - inline bool probe (bool (*fn)(msg_t &)) - { - scoped_lock_t lock (sync); - return (*fn) (*front); - } - - - private: - msg_t storage[2]; - msg_t *back, *front; - - mutex_t sync; - bool has_msg; - - // Disable copying of dbuffer. - dbuffer_t (const dbuffer_t&); - const dbuffer_t &operator = (const dbuffer_t&); - }; -} - -#endif diff --git a/src/dealer.cpp b/src/dealer.cpp deleted file mode 100644 index d330d0b..0000000 --- a/src/dealer.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "dealer.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::dealer_t::dealer_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - probe_router (false) -{ - options.type = ZMQ_DEALER; -} - -zmq::dealer_t::~dealer_t () -{ -} - -void zmq::dealer_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void) subscribe_to_all_; - - zmq_assert (pipe_); - - if (probe_router) { - msg_t probe_msg_; - int rc = probe_msg_.init (); - errno_assert (rc == 0); - - rc = pipe_->write (&probe_msg_); - // zmq_assert (rc) is not applicable here, since it is not a bug. - pipe_->flush (); - - rc = probe_msg_.close (); - errno_assert (rc == 0); - } - - fq.attach (pipe_); - lb.attach (pipe_); -} - -int zmq::dealer_t::xsetsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - bool is_int = (optvallen_ == sizeof (int)); - int value = is_int? *((int *) optval_): 0; - - switch (option_) { - case ZMQ_PROBE_ROUTER: - if (is_int && value >= 0) { - probe_router = (value != 0); - return 0; - } - break; - - default: - break; - } - - errno = EINVAL; - return -1; -} - -int zmq::dealer_t::xsend (msg_t *msg_) -{ - return sendpipe (msg_, NULL); -} - -int zmq::dealer_t::xrecv (msg_t *msg_) -{ - return recvpipe (msg_, NULL); -} - -bool zmq::dealer_t::xhas_in () -{ - return fq.has_in (); -} - -bool zmq::dealer_t::xhas_out () -{ - return lb.has_out (); -} - -void zmq::dealer_t::xread_activated (pipe_t *pipe_) -{ - fq.activated (pipe_); -} - -void zmq::dealer_t::xwrite_activated (pipe_t *pipe_) -{ - lb.activated (pipe_); -} - -void zmq::dealer_t::xpipe_terminated (pipe_t *pipe_) -{ - fq.pipe_terminated (pipe_); - lb.pipe_terminated (pipe_); -} - -int zmq::dealer_t::sendpipe (msg_t *msg_, pipe_t **pipe_) -{ - return lb.sendpipe (msg_, pipe_); -} - -int zmq::dealer_t::recvpipe (msg_t *msg_, pipe_t **pipe_) -{ - return fq.recvpipe (msg_, pipe_); -} diff --git a/src/dealer.hpp b/src/dealer.hpp deleted file mode 100644 index 0d6bb4c..0000000 --- a/src/dealer.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_DEALER_HPP_INCLUDED__ -#define __ZMQ_DEALER_HPP_INCLUDED__ - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "fq.hpp" -#include "lb.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class pipe_t; - class io_thread_t; - class socket_base_t; - - class dealer_t : - public socket_base_t - { - public: - - dealer_t (zmq::ctx_t *parent_, uint32_t tid_, int sid); - ~dealer_t (); - - protected: - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsetsockopt (int option_, const void *optval_, size_t optvallen_); - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - // Send and recv - knowing which pipe was used. - int sendpipe (zmq::msg_t *msg_, zmq::pipe_t **pipe_); - int recvpipe (zmq::msg_t *msg_, zmq::pipe_t **pipe_); - - private: - - // Messages are fair-queued from inbound pipes. And load-balanced to - // the outbound pipes. - fq_t fq; - lb_t lb; - - // if true, send an empty message to every connected router peer - bool probe_router; - - dealer_t (const dealer_t&); - const dealer_t &operator = (const dealer_t&); - }; - -} - -#endif diff --git a/src/decoder.hpp b/src/decoder.hpp deleted file mode 100644 index dca535b..0000000 --- a/src/decoder.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_DECODER_HPP_INCLUDED__ -#define __ZMQ_DECODER_HPP_INCLUDED__ - -#include <stddef.h> -#include <string.h> -#include <stdlib.h> -#include <algorithm> - -#include "err.hpp" -#include "msg.hpp" -#include "i_decoder.hpp" -#include "stdint.hpp" - -namespace zmq -{ - // Helper base class for decoders that know the amount of data to read - // in advance at any moment. Knowing the amount in advance is a property - // of the protocol used. 0MQ framing protocol is based size-prefixed - // paradigm, whixh qualifies it to be parsed by this class. - // On the other hand, XML-based transports (like XMPP or SOAP) don't allow - // for knowing the size of data to read in advance and should use different - // decoding algorithms. - // - // This class implements the state machine that parses the incoming buffer. - // Derived class should implement individual state machine actions. - - template <typename T> class decoder_base_t : public i_decoder - { - public: - - inline decoder_base_t (size_t bufsize_) : - next (NULL), - read_pos (NULL), - to_read (0), - bufsize (bufsize_) - { - buf = (unsigned char*) malloc (bufsize_); - alloc_assert (buf); - } - - // The destructor doesn't have to be virtual. It is mad virtual - // just to keep ICC and code checking tools from complaining. - inline virtual ~decoder_base_t () - { - free (buf); - } - - // Returns a buffer to be filled with binary data. - inline void get_buffer (unsigned char **data_, size_t *size_) - { - // If we are expected to read large message, we'll opt for zero- - // copy, i.e. we'll ask caller to fill the data directly to the - // message. Note that subsequent read(s) are non-blocking, thus - // each single read reads at most SO_RCVBUF bytes at once not - // depending on how large is the chunk returned from here. - // As a consequence, large messages being received won't block - // other engines running in the same I/O thread for excessive - // amounts of time. - if (to_read >= bufsize) { - *data_ = read_pos; - *size_ = to_read; - return; - } - - *data_ = buf; - *size_ = bufsize; - } - - // Processes the data in the buffer previously allocated using - // get_buffer function. size_ argument specifies nemuber of bytes - // actually filled into the buffer. Function returns 1 when the - // whole message was decoded or 0 when more data is required. - // On error, -1 is returned and errno set accordingly. - // Number of bytes processed is returned in byts_used_. - inline int decode (const unsigned char *data_, size_t size_, - size_t &bytes_used_) - { - bytes_used_ = 0; - - // In case of zero-copy simply adjust the pointers, no copying - // is required. Also, run the state machine in case all the data - // were processed. - if (data_ == read_pos) { - zmq_assert (size_ <= to_read); - read_pos += size_; - to_read -= size_; - bytes_used_ = size_; - - while (!to_read) { - const int rc = (static_cast <T*> (this)->*next) (); - if (rc != 0) - return rc; - } - return 0; - } - - while (bytes_used_ < size_) { - // Copy the data from buffer to the message. - const size_t to_copy = std::min (to_read, size_ - bytes_used_); - memcpy (read_pos, data_ + bytes_used_, to_copy); - read_pos += to_copy; - to_read -= to_copy; - bytes_used_ += to_copy; - // Try to get more space in the message to fill in. - // If none is available, return. - while (to_read == 0) { - const int rc = (static_cast <T*> (this)->*next) (); - if (rc != 0) - return rc; - } - } - - return 0; - } - - protected: - - // Prototype of state machine action. Action should return false if - // it is unable to push the data to the system. - typedef int (T::*step_t) (); - - // This function should be called from derived class to read data - // from the buffer and schedule next state machine action. - inline void next_step (void *read_pos_, size_t to_read_, step_t next_) - { - read_pos = (unsigned char*) read_pos_; - to_read = to_read_; - next = next_; - } - - private: - - // Next step. If set to NULL, it means that associated data stream - // is dead. Note that there can be still data in the process in such - // case. - step_t next; - - // Where to store the read data. - unsigned char *read_pos; - - // How much data to read before taking next step. - size_t to_read; - - // The duffer for data to decode. - size_t bufsize; - unsigned char *buf; - - decoder_base_t (const decoder_base_t&); - const decoder_base_t &operator = (const decoder_base_t&); - }; -} - -#endif - diff --git a/src/devpoll.cpp b/src/devpoll.cpp deleted file mode 100644 index 02b4a9c..0000000 --- a/src/devpoll.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "devpoll.hpp" -#if defined ZMQ_USE_DEVPOLL - -#include <sys/devpoll.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <limits.h> -#include <algorithm> - -#include "devpoll.hpp" -#include "err.hpp" -#include "config.hpp" -#include "i_poll_events.hpp" - -zmq::devpoll_t::devpoll_t () : - stopping (false) -{ - devpoll_fd = open ("/dev/poll", O_RDWR); - errno_assert (devpoll_fd != -1); -} - -zmq::devpoll_t::~devpoll_t () -{ - worker.stop (); - close (devpoll_fd); -} - -void zmq::devpoll_t::devpoll_ctl (fd_t fd_, short events_) -{ - struct pollfd pfd = {fd_, events_, 0}; - ssize_t rc = write (devpoll_fd, &pfd, sizeof pfd); - zmq_assert (rc == sizeof pfd); -} - -zmq::devpoll_t::handle_t zmq::devpoll_t::add_fd (fd_t fd_, - i_poll_events *reactor_) -{ - // If the file descriptor table is too small expand it. - fd_table_t::size_type sz = fd_table.size (); - if (sz <= (fd_table_t::size_type) fd_) { - fd_table.resize (fd_ + 1); - while (sz != (fd_table_t::size_type) (fd_ + 1)) { - fd_table [sz].valid = false; - ++sz; - } - } - - zmq_assert (!fd_table [fd_].valid); - - fd_table [fd_].events = 0; - fd_table [fd_].reactor = reactor_; - fd_table [fd_].valid = true; - fd_table [fd_].accepted = false; - - devpoll_ctl (fd_, 0); - pending_list.push_back (fd_); - - // Increase the load metric of the thread. - adjust_load (1); - - return fd_; -} - -void zmq::devpoll_t::rm_fd (handle_t handle_) -{ - zmq_assert (fd_table [handle_].valid); - - devpoll_ctl (handle_, POLLREMOVE); - fd_table [handle_].valid = false; - - // Decrease the load metric of the thread. - adjust_load (-1); -} - -void zmq::devpoll_t::set_pollin (handle_t handle_) -{ - devpoll_ctl (handle_, POLLREMOVE); - fd_table [handle_].events |= POLLIN; - devpoll_ctl (handle_, fd_table [handle_].events); -} - -void zmq::devpoll_t::reset_pollin (handle_t handle_) -{ - devpoll_ctl (handle_, POLLREMOVE); - fd_table [handle_].events &= ~((short) POLLIN); - devpoll_ctl (handle_, fd_table [handle_].events); -} - -void zmq::devpoll_t::set_pollout (handle_t handle_) -{ - devpoll_ctl (handle_, POLLREMOVE); - fd_table [handle_].events |= POLLOUT; - devpoll_ctl (handle_, fd_table [handle_].events); -} - -void zmq::devpoll_t::reset_pollout (handle_t handle_) -{ - devpoll_ctl (handle_, POLLREMOVE); - fd_table [handle_].events &= ~((short) POLLOUT); - devpoll_ctl (handle_, fd_table [handle_].events); -} - -void zmq::devpoll_t::start () -{ - worker.start (worker_routine, this); -} - -void zmq::devpoll_t::stop () -{ - stopping = true; -} - -int zmq::devpoll_t::max_fds () -{ - return -1; -} - -void zmq::devpoll_t::loop () -{ - while (!stopping) { - - struct pollfd ev_buf [max_io_events]; - struct dvpoll poll_req; - - for (pending_list_t::size_type i = 0; i < pending_list.size (); i ++) - fd_table [pending_list [i]].accepted = true; - pending_list.clear (); - - // Execute any due timers. - int timeout = (int) execute_timers (); - - // Wait for events. - // On Solaris, we can retrieve no more then (OPEN_MAX - 1) events. - poll_req.dp_fds = &ev_buf [0]; -#if defined ZMQ_HAVE_SOLARIS - poll_req.dp_nfds = std::min ((int) max_io_events, OPEN_MAX - 1); -#else - poll_req.dp_nfds = max_io_events; -#endif - poll_req.dp_timeout = timeout ? timeout : -1; - int n = ioctl (devpoll_fd, DP_POLL, &poll_req); - if (n == -1 && errno == EINTR) - continue; - errno_assert (n != -1); - - for (int i = 0; i < n; i ++) { - - fd_entry_t *fd_ptr = &fd_table [ev_buf [i].fd]; - if (!fd_ptr->valid || !fd_ptr->accepted) - continue; - if (ev_buf [i].revents & (POLLERR | POLLHUP)) - fd_ptr->reactor->in_event (); - if (!fd_ptr->valid || !fd_ptr->accepted) - continue; - if (ev_buf [i].revents & POLLOUT) - fd_ptr->reactor->out_event (); - if (!fd_ptr->valid || !fd_ptr->accepted) - continue; - if (ev_buf [i].revents & POLLIN) - fd_ptr->reactor->in_event (); - } - } -} - -void zmq::devpoll_t::worker_routine (void *arg_) -{ - ((devpoll_t*) arg_)->loop (); -} - -#endif diff --git a/src/devpoll.hpp b/src/devpoll.hpp deleted file mode 100644 index fbf9328..0000000 --- a/src/devpoll.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_DEVPOLL_HPP_INCLUDED__ -#define __ZMQ_DEVPOLL_HPP_INCLUDED__ - -// poller.hpp decides which polling mechanism to use. -#include "poller.hpp" -#if defined ZMQ_USE_DEVPOLL - -#include <vector> - -#include "fd.hpp" -#include "thread.hpp" -#include "poller_base.hpp" - -namespace zmq -{ - - struct i_poll_events; - - // Implements socket polling mechanism using the "/dev/poll" interface. - - class devpoll_t : public poller_base_t - { - public: - - typedef fd_t handle_t; - - devpoll_t (); - ~devpoll_t (); - - // "poller" concept. - handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void start (); - void stop (); - - static int max_fds (); - - private: - - // Main worker thread routine. - static void worker_routine (void *arg_); - - // Main event loop. - void loop (); - - // File descriptor referring to "/dev/poll" pseudo-device. - fd_t devpoll_fd; - - struct fd_entry_t - { - short events; - zmq::i_poll_events *reactor; - bool valid; - bool accepted; - }; - - typedef std::vector <fd_entry_t> fd_table_t; - fd_table_t fd_table; - - typedef std::vector <fd_t> pending_list_t; - pending_list_t pending_list; - - // Pollset manipulation function. - void devpoll_ctl (fd_t fd_, short events_); - - // If true, thread is in the process of shutting down. - bool stopping; - - // Handle of the physical thread doing the I/O work. - thread_t worker; - - devpoll_t (const devpoll_t&); - const devpoll_t &operator = (const devpoll_t&); - }; - - typedef devpoll_t poller_t; - -} - -#endif - -#endif diff --git a/src/dist.cpp b/src/dist.cpp deleted file mode 100755 index 5b19565..0000000 --- a/src/dist.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "dist.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" -#include "likely.hpp" - -zmq::dist_t::dist_t () : - matching (0), - active (0), - eligible (0), - more (false) -{ -} - -zmq::dist_t::~dist_t () -{ - zmq_assert (pipes.empty ()); -} - -void zmq::dist_t::attach (pipe_t *pipe_) -{ - // If we are in the middle of sending a message, we'll add new pipe - // into the list of eligible pipes. Otherwise we add it to the list - // of active pipes. - if (more) { - pipes.push_back (pipe_); - pipes.swap (eligible, pipes.size () - 1); - eligible++; - } - else { - pipes.push_back (pipe_); - pipes.swap (active, pipes.size () - 1); - active++; - eligible++; - } -} - -void zmq::dist_t::match (pipe_t *pipe_) -{ - // If pipe is already matching do nothing. - if (pipes.index (pipe_) < matching) - return; - - // If the pipe isn't eligible, ignore it. - if (pipes.index (pipe_) >= eligible) - return; - - // Mark the pipe as matching. - pipes.swap (pipes.index (pipe_), matching); - matching++; -} - -void zmq::dist_t::unmatch () -{ - matching = 0; -} - -void zmq::dist_t::pipe_terminated (pipe_t *pipe_) -{ - // Remove the pipe from the list; adjust number of matching, active and/or - // eligible pipes accordingly. - if (pipes.index (pipe_) < matching) { - pipes.swap (pipes.index (pipe_), matching - 1); - matching--; - } - if (pipes.index (pipe_) < active) { - pipes.swap (pipes.index (pipe_), active - 1); - active--; - } - if (pipes.index (pipe_) < eligible) { - pipes.swap (pipes.index (pipe_), eligible - 1); - eligible--; - } - - pipes.erase (pipe_); -} - -void zmq::dist_t::activated (pipe_t *pipe_) -{ - // Move the pipe from passive to eligible state. - pipes.swap (pipes.index (pipe_), eligible); - eligible++; - - // If there's no message being sent at the moment, move it to - // the active state. - if (!more) { - pipes.swap (eligible - 1, active); - active++; - } -} - -int zmq::dist_t::send_to_all (msg_t *msg_) -{ - matching = active; - return send_to_matching (msg_); -} - -int zmq::dist_t::send_to_matching (msg_t *msg_) -{ - // Is this end of a multipart message? - bool msg_more = msg_->flags () & msg_t::more ? true : false; - - // Push the message to matching pipes. - distribute (msg_); - - // If mutlipart message is fully sent, activate all the eligible pipes. - if (!msg_more) - active = eligible; - - more = msg_more; - - return 0; -} - -void zmq::dist_t::distribute (msg_t *msg_) -{ - // If there are no matching pipes available, simply drop the message. - if (matching == 0) { - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - return; - } - - if (msg_->is_vsm ()) { - for (pipes_t::size_type i = 0; i < matching; ++i) - if(!write (pipes [i], msg_)) - --i; // Retry last write because index will have been swapped - int rc = msg_->close(); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - return; - } - - // Add matching-1 references to the message. We already hold one reference, - // that's why -1. - msg_->add_refs ((int) matching - 1); - - // Push copy of the message to each matching pipe. - int failed = 0; - for (pipes_t::size_type i = 0; i < matching; ++i) - if (!write (pipes [i], msg_)) { - ++failed; - --i; // Retry last write because index will have been swapped - } - if (unlikely (failed)) - msg_->rm_refs (failed); - - // Detach the original message from the data buffer. Note that we don't - // close the message. That's because we've already used all the references. - int rc = msg_->init (); - errno_assert (rc == 0); -} - -bool zmq::dist_t::has_out () -{ - return true; -} - -bool zmq::dist_t::write (pipe_t *pipe_, msg_t *msg_) -{ - if (!pipe_->write (msg_)) { - pipes.swap (pipes.index (pipe_), matching - 1); - matching--; - pipes.swap (pipes.index (pipe_), active - 1); - active--; - pipes.swap (active, eligible - 1); - eligible--; - return false; - } - if (!(msg_->flags () & msg_t::more)) - pipe_->flush (); - return true; -} - diff --git a/src/dist.hpp b/src/dist.hpp deleted file mode 100644 index 6ad8b85..0000000 --- a/src/dist.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_DIST_HPP_INCLUDED__ -#define __ZMQ_DIST_HPP_INCLUDED__ - -#include <vector> - -#include "array.hpp" -#include "pipe.hpp" - -namespace zmq -{ - - class pipe_t; - class msg_t; - - // Class manages a set of outbound pipes. It sends each messages to - // each of them. - class dist_t - { - public: - - dist_t (); - ~dist_t (); - - // Adds the pipe to the distributor object. - void attach (zmq::pipe_t *pipe_); - - // Activates pipe that have previously reached high watermark. - void activated (zmq::pipe_t *pipe_); - - // Mark the pipe as matching. Subsequent call to send_to_matching - // will send message also to this pipe. - void match (zmq::pipe_t *pipe_); - - // Mark all pipes as non-matching. - void unmatch (); - - // Removes the pipe from the distributor object. - void pipe_terminated (zmq::pipe_t *pipe_); - - // Send the message to the matching outbound pipes. - int send_to_matching (zmq::msg_t *msg_); - - // Send the message to all the outbound pipes. - int send_to_all (zmq::msg_t *msg_); - - bool has_out (); - - private: - - // Write the message to the pipe. Make the pipe inactive if writing - // fails. In such a case false is returned. - bool write (zmq::pipe_t *pipe_, zmq::msg_t *msg_); - - // Put the message to all active pipes. - void distribute (zmq::msg_t *msg_); - - // List of outbound pipes. - typedef array_t <zmq::pipe_t, 2> pipes_t; - pipes_t pipes; - - // Number of all the pipes to send the next message to. - pipes_t::size_type matching; - - // Number of active pipes. All the active pipes are located at the - // beginning of the pipes array. These are the pipes the messages - // can be sent to at the moment. - pipes_t::size_type active; - - // Number of pipes eligible for sending messages to. This includes all - // the active pipes plus all the pipes that we can in theory send - // messages to (the HWM is not yet reached), but sending a message - // to them would result in partial message being delivered, ie. message - // with initial parts missing. - pipes_t::size_type eligible; - - // True if last we are in the middle of a multipart message. - bool more; - - dist_t (const dist_t&); - const dist_t &operator = (const dist_t&); - }; - -} - -#endif diff --git a/src/encoder.hpp b/src/encoder.hpp deleted file mode 100644 index 01ec366..0000000 --- a/src/encoder.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ENCODER_HPP_INCLUDED__ -#define __ZMQ_ENCODER_HPP_INCLUDED__ - -#if defined(_MSC_VER) -#ifndef NOMINMAX -#define NOMINMAX -#endif -#endif - -#include <stddef.h> -#include <string.h> -#include <stdlib.h> -#include <algorithm> - -#include "err.hpp" -#include "msg.hpp" -#include "i_encoder.hpp" - -namespace zmq -{ - - // Helper base class for encoders. It implements the state machine that - // fills the outgoing buffer. Derived classes should implement individual - // state machine actions. - - template <typename T> class encoder_base_t : public i_encoder - { - public: - - inline encoder_base_t (size_t bufsize_) : - bufsize (bufsize_), - in_progress (NULL) - { - buf = (unsigned char*) malloc (bufsize_); - alloc_assert (buf); - } - - // The destructor doesn't have to be virtual. It is made virtual - // just to keep ICC and code checking tools from complaining. - inline virtual ~encoder_base_t () - { - free (buf); - } - - // The function returns a batch of binary data. The data - // are filled to a supplied buffer. If no buffer is supplied (data_ - // points to NULL) decoder object will provide buffer of its own. - inline size_t encode (unsigned char **data_, size_t size_) - { - unsigned char *buffer = !*data_ ? buf : *data_; - size_t buffersize = !*data_ ? bufsize : size_; - - if (in_progress == NULL) - return 0; - - size_t pos = 0; - while (pos < buffersize) { - - // If there are no more data to return, run the state machine. - // If there are still no data, return what we already have - // in the buffer. - if (!to_write) { - if (new_msg_flag) { - int rc = in_progress->close (); - errno_assert (rc == 0); - rc = in_progress->init (); - errno_assert (rc == 0); - in_progress = NULL; - break; - } - (static_cast <T*> (this)->*next) (); - } - - // If there are no data in the buffer yet and we are able to - // fill whole buffer in a single go, let's use zero-copy. - // There's no disadvantage to it as we cannot stuck multiple - // messages into the buffer anyway. Note that subsequent - // write(s) are non-blocking, thus each single write writes - // at most SO_SNDBUF bytes at once not depending on how large - // is the chunk returned from here. - // As a consequence, large messages being sent won't block - // other engines running in the same I/O thread for excessive - // amounts of time. - if (!pos && !*data_ && to_write >= buffersize) { - *data_ = write_pos; - pos = to_write; - write_pos = NULL; - to_write = 0; - return pos; - } - - // Copy data to the buffer. If the buffer is full, return. - size_t to_copy = std::min (to_write, buffersize - pos); - memcpy (buffer + pos, write_pos, to_copy); - pos += to_copy; - write_pos += to_copy; - to_write -= to_copy; - } - - *data_ = buffer; - return pos; - } - - void load_msg (msg_t *msg_) - { - zmq_assert (in_progress == NULL); - in_progress = msg_; - (static_cast <T*> (this)->*next) (); - } - - protected: - - // Prototype of state machine action. - typedef void (T::*step_t) (); - - // This function should be called from derived class to write the data - // to the buffer and schedule next state machine action. - inline void next_step (void *write_pos_, size_t to_write_, - step_t next_, bool new_msg_flag_) - { - write_pos = (unsigned char*) write_pos_; - to_write = to_write_; - next = next_; - new_msg_flag = new_msg_flag_; - } - - private: - - // Where to get the data to write from. - unsigned char *write_pos; - - // How much data to write before next step should be executed. - size_t to_write; - - // Next step. If set to NULL, it means that associated data stream - // is dead. - step_t next; - - bool new_msg_flag; - - // The buffer for encoded data. - size_t bufsize; - unsigned char *buf; - - encoder_base_t (const encoder_base_t&); - void operator = (const encoder_base_t&); - - protected: - - msg_t *in_progress; - - }; -} - -#endif - diff --git a/src/epoll.cpp b/src/epoll.cpp deleted file mode 100644 index 492e06c..0000000 --- a/src/epoll.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "epoll.hpp" -#if defined ZMQ_USE_EPOLL - -#include <sys/epoll.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <algorithm> -#include <new> - -#include "epoll.hpp" -#include "err.hpp" -#include "config.hpp" -#include "i_poll_events.hpp" - -zmq::epoll_t::epoll_t () : - stopping (false) -{ - epoll_fd = epoll_create (1); - errno_assert (epoll_fd != -1); -} - -zmq::epoll_t::~epoll_t () -{ - // Wait till the worker thread exits. - worker.stop (); - - close (epoll_fd); - for (retired_t::iterator it = retired.begin (); it != retired.end (); ++it) - delete *it; -} - -zmq::epoll_t::handle_t zmq::epoll_t::add_fd (fd_t fd_, i_poll_events *events_) -{ - poll_entry_t *pe = new (std::nothrow) poll_entry_t; - alloc_assert (pe); - - // The memset is not actually needed. It's here to prevent debugging - // tools to complain about using uninitialised memory. - memset (pe, 0, sizeof (poll_entry_t)); - - pe->fd = fd_; - pe->ev.events = 0; - pe->ev.data.ptr = pe; - pe->events = events_; - - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_ADD, fd_, &pe->ev); - errno_assert (rc != -1); - - // Increase the load metric of the thread. - adjust_load (1); - - return pe; -} - -void zmq::epoll_t::rm_fd (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_DEL, pe->fd, &pe->ev); - errno_assert (rc != -1); - pe->fd = retired_fd; - retired.push_back (pe); - - // Decrease the load metric of the thread. - adjust_load (-1); -} - -void zmq::epoll_t::set_pollin (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - pe->ev.events |= EPOLLIN; - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); - errno_assert (rc != -1); -} - -void zmq::epoll_t::reset_pollin (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - pe->ev.events &= ~((short) EPOLLIN); - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); - errno_assert (rc != -1); -} - -void zmq::epoll_t::set_pollout (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - pe->ev.events |= EPOLLOUT; - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); - errno_assert (rc != -1); -} - -void zmq::epoll_t::reset_pollout (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - pe->ev.events &= ~((short) EPOLLOUT); - int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); - errno_assert (rc != -1); -} - -void zmq::epoll_t::start () -{ - worker.start (worker_routine, this); -} - -void zmq::epoll_t::stop () -{ - stopping = true; -} - -int zmq::epoll_t::max_fds () -{ - return -1; -} - -void zmq::epoll_t::loop () -{ - epoll_event ev_buf [max_io_events]; - - while (!stopping) { - - // Execute any due timers. - int timeout = (int) execute_timers (); - - // Wait for events. - int n = epoll_wait (epoll_fd, &ev_buf [0], max_io_events, - timeout ? timeout : -1); - if (n == -1) { - errno_assert (errno == EINTR); - continue; - } - - for (int i = 0; i < n; i ++) { - poll_entry_t *pe = ((poll_entry_t*) ev_buf [i].data.ptr); - - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].events & (EPOLLERR | EPOLLHUP)) - pe->events->in_event (); - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].events & EPOLLOUT) - pe->events->out_event (); - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].events & EPOLLIN) - pe->events->in_event (); - } - - // Destroy retired event sources. - for (retired_t::iterator it = retired.begin (); it != retired.end (); - ++it) - delete *it; - retired.clear (); - } -} - -void zmq::epoll_t::worker_routine (void *arg_) -{ - ((epoll_t*) arg_)->loop (); -} - -#endif diff --git a/src/epoll.hpp b/src/epoll.hpp deleted file mode 100644 index 0c89cb5..0000000 --- a/src/epoll.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_EPOLL_HPP_INCLUDED__ -#define __ZMQ_EPOLL_HPP_INCLUDED__ - -// poller.hpp decides which polling mechanism to use. -#include "poller.hpp" -#if defined ZMQ_USE_EPOLL - -#include <vector> -#include <sys/epoll.h> - -#include "fd.hpp" -#include "thread.hpp" -#include "poller_base.hpp" - -namespace zmq -{ - - struct i_poll_events; - - // This class implements socket polling mechanism using the Linux-specific - // epoll mechanism. - - class epoll_t : public poller_base_t - { - public: - - typedef void* handle_t; - - epoll_t (); - ~epoll_t (); - - // "poller" concept. - handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void start (); - void stop (); - - static int max_fds (); - - private: - - // Main worker thread routine. - static void worker_routine (void *arg_); - - // Main event loop. - void loop (); - - // Main epoll file descriptor - fd_t epoll_fd; - - struct poll_entry_t - { - fd_t fd; - epoll_event ev; - zmq::i_poll_events *events; - }; - - // List of retired event sources. - typedef std::vector <poll_entry_t*> retired_t; - retired_t retired; - - // If true, thread is in the process of shutting down. - bool stopping; - - // Handle of the physical thread doing the I/O work. - thread_t worker; - - epoll_t (const epoll_t&); - const epoll_t &operator = (const epoll_t&); - }; - - typedef epoll_t poller_t; - -} - -#endif - -#endif diff --git a/src/err.cpp b/src/err.cpp deleted file mode 100644 index 8d829be..0000000 --- a/src/err.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "err.hpp" -#include "platform.hpp" - -const char *zmq::errno_to_string (int errno_) -{ - switch (errno_) { -#if defined ZMQ_HAVE_WINDOWS - case ENOTSUP: - return "Not supported"; - case EPROTONOSUPPORT: - return "Protocol not supported"; - case ENOBUFS: - return "No buffer space available"; - case ENETDOWN: - return "Network is down"; - case EADDRINUSE: - return "Address in use"; - case EADDRNOTAVAIL: - return "Address not available"; - case ECONNREFUSED: - return "Connection refused"; - case EINPROGRESS: - return "Operation in progress"; -#endif - case EFSM: - return "Operation cannot be accomplished in current state"; - case ENOCOMPATPROTO: - return "The protocol is not compatible with the socket type"; - case ETERM: - return "Context was terminated"; - case EMTHREAD: - return "No thread available"; - default: -#if defined _MSC_VER -#pragma warning (push) -#pragma warning (disable:4996) -#endif - return strerror (errno_); -#if defined _MSC_VER -#pragma warning (pop) -#endif - } -} - -void zmq::zmq_abort(const char *errmsg_) -{ -#if defined ZMQ_HAVE_WINDOWS - - // Raise STATUS_FATAL_APP_EXIT. - ULONG_PTR extra_info [1]; - extra_info [0] = (ULONG_PTR) errmsg_; - RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info); -#else - (void)errmsg_; - abort (); -#endif -} - -#ifdef ZMQ_HAVE_WINDOWS - -const char *zmq::wsa_error() -{ - int no = WSAGetLastError (); - // TODO: This is not a generic way to handle this... - if (no == WSAEWOULDBLOCK) - return NULL; - - return wsa_error_no (no); -} - -const char *zmq::wsa_error_no (int no_) -{ - // TODO: It seems that list of Windows socket errors is longer than this. - // Investigate whether there's a way to convert it into the string - // automatically (wsaError->HRESULT->string?). - return - (no_ == WSABASEERR) ? - "No Error" : - (no_ == WSAEINTR) ? - "Interrupted system call" : - (no_ == WSAEBADF) ? - "Bad file number" : - (no_ == WSAEACCES) ? - "Permission denied" : - (no_ == WSAEFAULT) ? - "Bad address" : - (no_ == WSAEINVAL) ? - "Invalid argument" : - (no_ == WSAEMFILE) ? - "Too many open files" : - (no_ == WSAEWOULDBLOCK) ? - "Operation would block" : - (no_ == WSAEINPROGRESS) ? - "Operation now in progress" : - (no_ == WSAEALREADY) ? - "Operation already in progress" : - (no_ == WSAENOTSOCK) ? - "Socket operation on non-socket" : - (no_ == WSAEDESTADDRREQ) ? - "Destination address required" : - (no_ == WSAEMSGSIZE) ? - "Message too long" : - (no_ == WSAEPROTOTYPE) ? - "Protocol wrong type for socket" : - (no_ == WSAENOPROTOOPT) ? - "Bad protocol option" : - (no_ == WSAEPROTONOSUPPORT) ? - "Protocol not supported" : - (no_ == WSAESOCKTNOSUPPORT) ? - "Socket type not supported" : - (no_ == WSAEOPNOTSUPP) ? - "Operation not supported on socket" : - (no_ == WSAEPFNOSUPPORT) ? - "Protocol family not supported" : - (no_ == WSAEAFNOSUPPORT) ? - "Address family not supported by protocol family" : - (no_ == WSAEADDRINUSE) ? - "Address already in use" : - (no_ == WSAEADDRNOTAVAIL) ? - "Can't assign requested address" : - (no_ == WSAENETDOWN) ? - "Network is down" : - (no_ == WSAENETUNREACH) ? - "Network is unreachable" : - (no_ == WSAENETRESET) ? - "Net dropped connection or reset" : - (no_ == WSAECONNABORTED) ? - "Software caused connection abort" : - (no_ == WSAECONNRESET) ? - "Connection reset by peer" : - (no_ == WSAENOBUFS) ? - "No buffer space available" : - (no_ == WSAEISCONN) ? - "Socket is already connected" : - (no_ == WSAENOTCONN) ? - "Socket is not connected" : - (no_ == WSAESHUTDOWN) ? - "Can't send after socket shutdown" : - (no_ == WSAETOOMANYREFS) ? - "Too many references can't splice" : - (no_ == WSAETIMEDOUT) ? - "Connection timed out" : - (no_ == WSAECONNREFUSED) ? - "Connection refused" : - (no_ == WSAELOOP) ? - "Too many levels of symbolic links" : - (no_ == WSAENAMETOOLONG) ? - "File name too long" : - (no_ == WSAEHOSTDOWN) ? - "Host is down" : - (no_ == WSAEHOSTUNREACH) ? - "No Route to Host" : - (no_ == WSAENOTEMPTY) ? - "Directory not empty" : - (no_ == WSAEPROCLIM) ? - "Too many processes" : - (no_ == WSAEUSERS) ? - "Too many users" : - (no_ == WSAEDQUOT) ? - "Disc Quota Exceeded" : - (no_ == WSAESTALE) ? - "Stale NFS file handle" : - (no_ == WSAEREMOTE) ? - "Too many levels of remote in path" : - (no_ == WSASYSNOTREADY) ? - "Network SubSystem is unavailable" : - (no_ == WSAVERNOTSUPPORTED) ? - "WINSOCK DLL Version out of range" : - (no_ == WSANOTINITIALISED) ? - "Successful WSASTARTUP not yet performed" : - (no_ == WSAHOST_NOT_FOUND) ? - "Host not found" : - (no_ == WSATRY_AGAIN) ? - "Non-Authoritative Host not found" : - (no_ == WSANO_RECOVERY) ? - "Non-Recoverable errors: FORMERR REFUSED NOTIMP" : - (no_ == WSANO_DATA) ? - "Valid name no data record of requested" : - "error not defined"; -} - -void zmq::win_error (char *buffer_, size_t buffer_size_) -{ - DWORD errcode = GetLastError (); -#if defined _WIN32_WCE - DWORD rc = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), (LPWSTR)buffer_, buffer_size_ / sizeof(wchar_t), NULL ); -#else - DWORD rc = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), buffer_, (DWORD) buffer_size_, NULL ); -#endif - zmq_assert (rc); -} - -int zmq::wsa_error_to_errno (int errcode) -{ - switch (errcode) { -// 10009 - File handle is not valid. - case WSAEBADF: - return EBADF; -// 10013 - Permission denied. - case WSAEACCES: - return EACCES; -// 10014 - Bad address. - case WSAEFAULT: - return EFAULT; -// 10022 - Invalid argument. - case WSAEINVAL: - return EINVAL; -// 10024 - Too many open files. - case WSAEMFILE: - return EMFILE; -// 10036 - Operation now in progress. - case WSAEINPROGRESS: - return EAGAIN; -// 10040 - Message too long. - case WSAEMSGSIZE: - return EMSGSIZE; -// 10043 - Protocol not supported. - case WSAEPROTONOSUPPORT: - return EPROTONOSUPPORT; -// 10047 - Address family not supported by protocol family. - case WSAEAFNOSUPPORT: - return EAFNOSUPPORT; -// 10048 - Address already in use. - case WSAEADDRINUSE: - return EADDRINUSE; -// 10049 - Cannot assign requested address. - case WSAEADDRNOTAVAIL: - return EADDRNOTAVAIL; -// 10050 - Network is down. - case WSAENETDOWN: - return ENETDOWN; -// 10051 - Network is unreachable. - case WSAENETUNREACH: - return ENETUNREACH; -// 10052 - Network dropped connection on reset. - case WSAENETRESET: - return ENETRESET; -// 10053 - Software caused connection abort. - case WSAECONNABORTED: - return ECONNABORTED; -// 10054 - Connection reset by peer. - case WSAECONNRESET: - return ECONNRESET; -// 10055 - No buffer space available. - case WSAENOBUFS: - return ENOBUFS; -// 10057 - Socket is not connected. - case WSAENOTCONN: - return ENOTCONN; -// 10060 - Connection timed out. - case WSAETIMEDOUT: - return ETIMEDOUT; -// 10061 - Connection refused. - case WSAECONNREFUSED: - return ECONNREFUSED; -// 10065 - No route to host. - case WSAEHOSTUNREACH: - return EHOSTUNREACH; - default: - wsa_assert (false); - } - // Not reachable - return 0; -} - -#endif diff --git a/src/err.hpp b/src/err.hpp deleted file mode 100644 index 7076f11..0000000 --- a/src/err.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ERR_HPP_INCLUDED__ -#define __ZMQ_ERR_HPP_INCLUDED__ - -// 0MQ-specific error codes are defined in zmq.h -#include "../include/zmq.h" - -#include <assert.h> -#if defined _WIN32_WCE -#include "..\builds\msvc\errno.hpp" -#else -#include <errno.h> -#endif -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "platform.hpp" -#include "likely.hpp" - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <netdb.h> -#endif - -// EPROTO is not used by OpenBSD and maybe other platforms. -#ifndef EPROTO -#define EPROTO 0 -#endif - -namespace zmq -{ - const char *errno_to_string (int errno_); - void zmq_abort (const char *errmsg_); -} - -#ifdef ZMQ_HAVE_WINDOWS - -namespace zmq -{ - const char *wsa_error (); - const char *wsa_error_no (int no_); - void win_error (char *buffer_, size_t buffer_size_); - int wsa_error_to_errno (int errcode); -} - -// Provides convenient way to check WSA-style errors on Windows. -#define wsa_assert(x) \ - do {\ - if (unlikely (!(x))) {\ - const char *errstr = zmq::wsa_error ();\ - if (errstr != NULL) {\ - fprintf (stderr, "Assertion failed: %s (%s:%d)\n", errstr, \ - __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - }\ - } while (false) - -// Provides convenient way to assert on WSA-style errors on Windows. -#define wsa_assert_no(no) \ - do {\ - const char *errstr = zmq::wsa_error_no (no);\ - if (errstr != NULL) {\ - fprintf (stderr, "Assertion failed: %s (%s:%d)\n", errstr, \ - __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - } while (false) - -// Provides convenient way to check GetLastError-style errors on Windows. -#define win_assert(x) \ - do {\ - if (unlikely (!(x))) {\ - char errstr [256];\ - zmq::win_error (errstr, 256);\ - fprintf (stderr, "Assertion failed: %s (%s:%d)\n", errstr, \ - __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - } while (false) - -#endif - -// This macro works in exactly the same way as the normal assert. It is used -// in its stead because standard assert on Win32 in broken - it prints nothing -// when used within the scope of JNI library. -#define zmq_assert(x) \ - do {\ - if (unlikely (!(x))) {\ - fprintf (stderr, "Assertion failed: %s (%s:%d)\n", #x, \ - __FILE__, __LINE__);\ - zmq::zmq_abort (#x);\ - }\ - } while (false) - -// Provides convenient way to check for errno-style errors. -#define errno_assert(x) \ - do {\ - if (unlikely (!(x))) {\ - const char *errstr = strerror (errno);\ - fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - } while (false) - -// Provides convenient way to check for POSIX errors. -#define posix_assert(x) \ - do {\ - if (unlikely (x)) {\ - const char *errstr = strerror (x);\ - fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - } while (false) - -// Provides convenient way to check for errors from getaddrinfo. -#define gai_assert(x) \ - do {\ - if (unlikely (x)) {\ - const char *errstr = gai_strerror (x);\ - fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__);\ - zmq::zmq_abort (errstr);\ - }\ - } while (false) - -// Provides convenient way to check whether memory allocation have succeeded. -#define alloc_assert(x) \ - do {\ - if (unlikely (!x)) {\ - fprintf (stderr, "FATAL ERROR: OUT OF MEMORY (%s:%d)\n",\ - __FILE__, __LINE__);\ - zmq::zmq_abort ("FATAL ERROR: OUT OF MEMORY");\ - }\ - } while (false) - -#endif - - diff --git a/src/fd.hpp b/src/fd.hpp deleted file mode 100644 index 55a2e9b..0000000 --- a/src/fd.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_FD_HPP_INCLUDED__ -#define __ZMQ_FD_HPP_INCLUDED__ - -#include "platform.hpp" - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -namespace zmq -{ -#ifdef ZMQ_HAVE_WINDOWS -#if defined _MSC_VER &&_MSC_VER <= 1400 - typedef UINT_PTR fd_t; - enum {retired_fd = (fd_t)(~0)}; -#else - typedef SOCKET fd_t; - enum {retired_fd = (fd_t)INVALID_SOCKET}; -#endif -#else - typedef int fd_t; - enum {retired_fd = -1}; -#endif -} -#endif diff --git a/src/fq.cpp b/src/fq.cpp deleted file mode 100644 index aa099eb..0000000 --- a/src/fq.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "fq.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::fq_t::fq_t () : - active (0), - current (0), - more (false) -{ -} - -zmq::fq_t::~fq_t () -{ - zmq_assert (pipes.empty ()); -} - -void zmq::fq_t::attach (pipe_t *pipe_) -{ - pipes.push_back (pipe_); - pipes.swap (active, pipes.size () - 1); - active++; -} - -void zmq::fq_t::pipe_terminated (pipe_t *pipe_) -{ - const pipes_t::size_type index = pipes.index (pipe_); - - // Remove the pipe from the list; adjust number of active pipes - // accordingly. - if (index < active) { - active--; - pipes.swap (index, active); - if (current == active) - current = 0; - } - pipes.erase (pipe_); -} - -void zmq::fq_t::activated (pipe_t *pipe_) -{ - // Move the pipe to the list of active pipes. - pipes.swap (pipes.index (pipe_), active); - active++; -} - -int zmq::fq_t::recv (msg_t *msg_) -{ - return recvpipe (msg_, NULL); -} - -int zmq::fq_t::recvpipe (msg_t *msg_, pipe_t **pipe_) -{ - // Deallocate old content of the message. - int rc = msg_->close (); - errno_assert (rc == 0); - - // Round-robin over the pipes to get the next message. - while (active > 0) { - - // Try to fetch new message. If we've already read part of the message - // subsequent part should be immediately available. - bool fetched = pipes [current]->read (msg_); - - // Note that when message is not fetched, current pipe is deactivated - // and replaced by another active pipe. Thus we don't have to increase - // the 'current' pointer. - if (fetched) { - if (pipe_) - *pipe_ = pipes [current]; - more = msg_->flags () & msg_t::more? true: false; - if (!more) - current = (current + 1) % active; - return 0; - } - - // Check the atomicity of the message. - // If we've already received the first part of the message - // we should get the remaining parts without blocking. - zmq_assert (!more); - - active--; - pipes.swap (current, active); - if (current == active) - current = 0; - } - - // No message is available. Initialise the output parameter - // to be a 0-byte message. - rc = msg_->init (); - errno_assert (rc == 0); - errno = EAGAIN; - return -1; -} - -bool zmq::fq_t::has_in () -{ - // There are subsequent parts of the partly-read message available. - if (more) - return true; - - // Note that messing with current doesn't break the fairness of fair - // queueing algorithm. If there are no messages available current will - // get back to its original value. Otherwise it'll point to the first - // pipe holding messages, skipping only pipes with no messages available. - while (active > 0) { - if (pipes [current]->check_read ()) - return true; - - // Deactivate the pipe. - active--; - pipes.swap (current, active); - if (current == active) - current = 0; - } - - return false; -} - diff --git a/src/fq.hpp b/src/fq.hpp deleted file mode 100644 index 843731b..0000000 --- a/src/fq.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_FQ_HPP_INCLUDED__ -#define __ZMQ_FQ_HPP_INCLUDED__ - -#include "array.hpp" -#include "pipe.hpp" -#include "msg.hpp" - -namespace zmq -{ - - // Class manages a set of inbound pipes. On receive it performs fair - // queueing so that senders gone berserk won't cause denial of - // service for decent senders. - - class fq_t - { - public: - - fq_t (); - ~fq_t (); - - void attach (pipe_t *pipe_); - void activated (pipe_t *pipe_); - void pipe_terminated (pipe_t *pipe_); - - int recv (msg_t *msg_); - int recvpipe (msg_t *msg_, pipe_t **pipe_); - bool has_in (); - - private: - - // Inbound pipes. - typedef array_t <pipe_t, 1> pipes_t; - pipes_t pipes; - - // Number of active pipes. All the active pipes are located at the - // beginning of the pipes array. - pipes_t::size_type active; - - // Index of the next bound pipe to read a message from. - pipes_t::size_type current; - - // If true, part of a multipart message was already received, but - // there are following parts still waiting in the current pipe. - bool more; - - fq_t (const fq_t&); - const fq_t &operator = (const fq_t&); - }; - -} - -#endif diff --git a/src/i_decoder.hpp b/src/i_decoder.hpp deleted file mode 100644 index db62dab..0000000 --- a/src/i_decoder.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_I_DECODER_HPP_INCLUDED__ -#define __ZMQ_I_DECODER_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - class msg_t; - - // Interface to be implemented by message decoder. - - class i_decoder - { - public: - virtual ~i_decoder () {} - - virtual void get_buffer (unsigned char **data_, size_t *size_) = 0; - - // Decodes data pointed to by data_. - // When a message is decoded, 1 is returned. - // When the decoder needs more data, 0 is returnd. - // On error, -1 is returned and errno is set accordingly. - virtual int decode (const unsigned char *data_, size_t size_, - size_t &processed) = 0; - - virtual msg_t *msg () = 0; - }; - -} - -#endif diff --git a/src/i_encoder.hpp b/src/i_encoder.hpp deleted file mode 100644 index e0318e1..0000000 --- a/src/i_encoder.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_I_ENCODER_HPP_INCLUDED__ -#define __ZMQ_I_ENCODER_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - // Forward declaration - class msg_t; - - // Interface to be implemented by message encoder. - - struct i_encoder - { - virtual ~i_encoder () {} - - // The function returns a batch of binary data. The data - // are filled to a supplied buffer. If no buffer is supplied (data_ - // is NULL) encoder will provide buffer of its own. - // Function returns 0 when a new message is required. - virtual size_t encode (unsigned char **data_, size_t size) = 0; - - // Load a new message into encoder. - virtual void load_msg (msg_t *msg_) = 0; - - }; - -} - -#endif diff --git a/src/i_engine.hpp b/src/i_engine.hpp deleted file mode 100644 index 39266c4..0000000 --- a/src/i_engine.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_I_ENGINE_HPP_INCLUDED__ -#define __ZMQ_I_ENGINE_HPP_INCLUDED__ - -namespace zmq -{ - - class io_thread_t; - - // Abstract interface to be implemented by various engines. - - struct i_engine - { - virtual ~i_engine () {} - - // Plug the engine to the session. - virtual void plug (zmq::io_thread_t *io_thread_, - class session_base_t *session_) = 0; - - // Terminate and deallocate the engine. Note that 'detached' - // events are not fired on termination. - virtual void terminate () = 0; - - // This method is called by the session to signalise that more - // messages can be written to the pipe. - virtual void restart_input () = 0; - - // This method is called by the session to signalise that there - // are messages to send available. - virtual void restart_output () = 0; - - virtual void zap_msg_available () = 0; - }; - -} - -#endif diff --git a/src/i_poll_events.hpp b/src/i_poll_events.hpp deleted file mode 100644 index bcf496e..0000000 --- a/src/i_poll_events.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_I_POLL_EVENTS_HPP_INCLUDED__ -#define __ZMQ_I_POLL_EVENTS_HPP_INCLUDED__ - -namespace zmq -{ - - // Virtual interface to be exposed by object that want to be notified - // about events on file descriptors. - - struct i_poll_events - { - virtual ~i_poll_events () {} - - // Called by I/O thread when file descriptor is ready for reading. - virtual void in_event () = 0; - - // Called by I/O thread when file descriptor is ready for writing. - virtual void out_event () = 0; - - // Called when timer expires. - virtual void timer_event (int id_) = 0; - }; - -} - -#endif diff --git a/src/io_object.cpp b/src/io_object.cpp deleted file mode 100644 index 258b52c..0000000 --- a/src/io_object.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "io_object.hpp" -#include "io_thread.hpp" -#include "err.hpp" - -zmq::io_object_t::io_object_t (io_thread_t *io_thread_) : - poller (NULL) -{ - if (io_thread_) - plug (io_thread_); -} - -zmq::io_object_t::~io_object_t () -{ -} - -void zmq::io_object_t::plug (io_thread_t *io_thread_) -{ - zmq_assert (io_thread_); - zmq_assert (!poller); - - // Retrieve the poller from the thread we are running in. - poller = io_thread_->get_poller (); -} - -void zmq::io_object_t::unplug () -{ - zmq_assert (poller); - - // Forget about old poller in preparation to be migrated - // to a different I/O thread. - poller = NULL; -} - -zmq::io_object_t::handle_t zmq::io_object_t::add_fd (fd_t fd_) -{ - return poller->add_fd (fd_, this); -} - -void zmq::io_object_t::rm_fd (handle_t handle_) -{ - poller->rm_fd (handle_); -} - -void zmq::io_object_t::set_pollin (handle_t handle_) -{ - poller->set_pollin (handle_); -} - -void zmq::io_object_t::reset_pollin (handle_t handle_) -{ - poller->reset_pollin (handle_); -} - -void zmq::io_object_t::set_pollout (handle_t handle_) -{ - poller->set_pollout (handle_); -} - -void zmq::io_object_t::reset_pollout (handle_t handle_) -{ - poller->reset_pollout (handle_); -} - -void zmq::io_object_t::add_timer (int timeout_, int id_) -{ - poller->add_timer (timeout_, this, id_); -} - -void zmq::io_object_t::cancel_timer (int id_) -{ - poller->cancel_timer (this, id_); -} - -void zmq::io_object_t::in_event () -{ - zmq_assert (false); -} - -void zmq::io_object_t::out_event () -{ - zmq_assert (false); -} - -void zmq::io_object_t::timer_event (int) -{ - zmq_assert (false); -} diff --git a/src/io_object.hpp b/src/io_object.hpp deleted file mode 100644 index 16e0b5f..0000000 --- a/src/io_object.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_IO_OBJECT_HPP_INCLUDED__ -#define __ZMQ_IO_OBJECT_HPP_INCLUDED__ - -#include <stddef.h> - -#include "stdint.hpp" -#include "poller.hpp" -#include "i_poll_events.hpp" - -namespace zmq -{ - - class io_thread_t; - - // Simple base class for objects that live in I/O threads. - // It makes communication with the poller object easier and - // makes defining unneeded event handlers unnecessary. - - class io_object_t : public i_poll_events - { - public: - - io_object_t (zmq::io_thread_t *io_thread_ = NULL); - ~io_object_t (); - - // When migrating an object from one I/O thread to another, first - // unplug it, then migrate it, then plug it to the new thread. - void plug (zmq::io_thread_t *io_thread_); - void unplug (); - - protected: - - typedef poller_t::handle_t handle_t; - - // Methods to access underlying poller object. - handle_t add_fd (fd_t fd_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void add_timer (int timout_, int id_); - void cancel_timer (int id_); - - // i_poll_events interface implementation. - void in_event (); - void out_event (); - void timer_event (int id_); - - private: - - poller_t *poller; - - io_object_t (const io_object_t&); - const io_object_t &operator = (const io_object_t&); - }; - -} - -#endif diff --git a/src/io_thread.cpp b/src/io_thread.cpp deleted file mode 100644 index 5633a02..0000000 --- a/src/io_thread.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <new> - -#include "io_thread.hpp" -#include "platform.hpp" -#include "err.hpp" -#include "ctx.hpp" - -zmq::io_thread_t::io_thread_t (ctx_t *ctx_, uint32_t tid_) : - object_t (ctx_, tid_) -{ - poller = new (std::nothrow) poller_t; - alloc_assert (poller); - - mailbox_handle = poller->add_fd (mailbox.get_fd (), this); - poller->set_pollin (mailbox_handle); -} - -zmq::io_thread_t::~io_thread_t () -{ - delete poller; -} - -void zmq::io_thread_t::start () -{ - // Start the underlying I/O thread. - poller->start (); -} - -void zmq::io_thread_t::stop () -{ - send_stop (); -} - -zmq::mailbox_t *zmq::io_thread_t::get_mailbox () -{ - return &mailbox; -} - -int zmq::io_thread_t::get_load () -{ - return poller->get_load (); -} - -void zmq::io_thread_t::in_event () -{ - // TODO: Do we want to limit number of commands I/O thread can - // process in a single go? - - command_t cmd; - int rc = mailbox.recv (&cmd, 0); - - while (rc == 0 || errno == EINTR) { - if (rc == 0) - cmd.destination->process_command (cmd); - rc = mailbox.recv (&cmd, 0); - } - - errno_assert (rc != 0 && errno == EAGAIN); -} - -void zmq::io_thread_t::out_event () -{ - // We are never polling for POLLOUT here. This function is never called. - zmq_assert (false); -} - -void zmq::io_thread_t::timer_event (int) -{ - // No timers here. This function is never called. - zmq_assert (false); -} - -zmq::poller_t *zmq::io_thread_t::get_poller () -{ - zmq_assert (poller); - return poller; -} - -void zmq::io_thread_t::process_stop () -{ - poller->rm_fd (mailbox_handle); - poller->stop (); -} diff --git a/src/io_thread.hpp b/src/io_thread.hpp deleted file mode 100644 index 32f51df..0000000 --- a/src/io_thread.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_IO_THREAD_HPP_INCLUDED__ -#define __ZMQ_IO_THREAD_HPP_INCLUDED__ - -#include <vector> - -#include "stdint.hpp" -#include "object.hpp" -#include "poller.hpp" -#include "i_poll_events.hpp" -#include "mailbox.hpp" - -namespace zmq -{ - - class ctx_t; - - // Generic part of the I/O thread. Polling-mechanism-specific features - // are implemented in separate "polling objects". - - class io_thread_t : public object_t, public i_poll_events - { - public: - - io_thread_t (zmq::ctx_t *ctx_, uint32_t tid_); - - // Clean-up. If the thread was started, it's neccessary to call 'stop' - // before invoking destructor. Otherwise the destructor would hang up. - ~io_thread_t (); - - // Launch the physical thread. - void start (); - - // Ask underlying thread to stop. - void stop (); - - // Returns mailbox associated with this I/O thread. - mailbox_t *get_mailbox (); - - // i_poll_events implementation. - void in_event (); - void out_event (); - void timer_event (int id_); - - // Used by io_objects to retrieve the assciated poller object. - poller_t *get_poller (); - - // Command handlers. - void process_stop (); - - // Returns load experienced by the I/O thread. - int get_load (); - - private: - - // I/O thread accesses incoming commands via this mailbox. - mailbox_t mailbox; - - // Handle associated with mailbox' file descriptor. - poller_t::handle_t mailbox_handle; - - // I/O multiplexing is performed using a poller object. - poller_t *poller; - - io_thread_t (const io_thread_t&); - const io_thread_t &operator = (const io_thread_t&); - }; - -} - -#endif diff --git a/src/ip.cpp b/src/ip.cpp deleted file mode 100644 index f11cab8..0000000 --- a/src/ip.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ip.hpp" -#include "err.hpp" -#include "platform.hpp" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#endif - -#if defined ZMQ_HAVE_OPENVMS -#include <ioctl.h> -#endif - -zmq::fd_t zmq::open_socket (int domain_, int type_, int protocol_) -{ - // Setting this option result in sane behaviour when exec() functions - // are used. Old sockets are closed and don't block TCP ports etc. -#if defined ZMQ_HAVE_SOCK_CLOEXEC - type_ |= SOCK_CLOEXEC; -#endif - - fd_t s = socket (domain_, type_, protocol_); -#ifdef ZMQ_HAVE_WINDOWS - if (s == INVALID_SOCKET) - return INVALID_SOCKET; -#else - if (s == -1) - return -1; -#endif - - // If there's no SOCK_CLOEXEC, let's try the second best option. Note that - // race condition can cause socket not to be closed (if fork happens - // between socket creation and this point). -#if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC - int rc = fcntl (s, F_SETFD, FD_CLOEXEC); - errno_assert (rc != -1); -#endif - - // On Windows, preventing sockets to be inherited by child processes. -#if defined ZMQ_HAVE_WINDOWS && defined HANDLE_FLAG_INHERIT - BOOL brc = SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); - win_assert (brc); -#endif - - return s; -} - -void zmq::unblock_socket (fd_t s_) -{ -#if defined ZMQ_HAVE_WINDOWS - u_long nonblock = 1; - int rc = ioctlsocket (s_, FIONBIO, &nonblock); - wsa_assert (rc != SOCKET_ERROR); -#elif defined ZMQ_HAVE_OPENVMS - int nonblock = 1; - int rc = ioctl (s_, FIONBIO, &nonblock); - errno_assert (rc != -1); -#else - int flags = fcntl (s_, F_GETFL, 0); - if (flags == -1) - flags = 0; - int rc = fcntl (s_, F_SETFL, flags | O_NONBLOCK); - errno_assert (rc != -1); -#endif -} - -void zmq::enable_ipv4_mapping (fd_t s_) -{ - (void) s_; - -#ifdef IPV6_V6ONLY -#ifdef ZMQ_HAVE_WINDOWS - DWORD flag = 0; -#else - int flag = 0; -#endif - int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &flag, - sizeof (flag)); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else - errno_assert (rc == 0); -#endif -#endif -} - -bool zmq::get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_) -{ - int rc; - struct sockaddr_storage ss; - -#if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_WINDOWS - int addrlen = static_cast <int> (sizeof ss); -#else - socklen_t addrlen = sizeof ss; -#endif - rc = getpeername (sockfd_, (struct sockaddr*) &ss, &addrlen); -#ifdef ZMQ_HAVE_WINDOWS - if (rc == SOCKET_ERROR) { - wsa_assert (WSAGetLastError () != WSANOTINITIALISED && - WSAGetLastError () != WSAEFAULT && - WSAGetLastError () != WSAEINPROGRESS && - WSAGetLastError () != WSAENOTSOCK); - return false; - } -#else - if (rc == -1) { - errno_assert (errno != EBADF && - errno != EFAULT && - errno != EINVAL && - errno != ENOTSOCK); - return false; - } -#endif - - char host [NI_MAXHOST]; - rc = getnameinfo ((struct sockaddr*) &ss, addrlen, host, sizeof host, - NULL, 0, NI_NUMERICHOST); - if (rc != 0) - return false; - - ip_addr_ = host; - return true; -} diff --git a/src/ip.hpp b/src/ip.hpp deleted file mode 100644 index 7d0bb84..0000000 --- a/src/ip.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_IP_HPP_INCLUDED__ -#define __ZMQ_IP_HPP_INCLUDED__ - -#include <string> -#include "fd.hpp" - -namespace zmq -{ - - // Same as socket(2), but allows for transparent tweaking the options. - fd_t open_socket (int domain_, int type_, int protocol_); - - // Sets the socket into non-blocking mode. - void unblock_socket (fd_t s_); - - // Enable IPv4-mapping of addresses in case it is disabled by default. - void enable_ipv4_mapping (fd_t s_); - - // Returns string representation of peer's address. - // Socket sockfd_ must be connected. Returns true iff successful. - bool get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_); - -} - -#endif diff --git a/src/ipc_address.cpp b/src/ipc_address.cpp deleted file mode 100644 index e3d23fa..0000000 --- a/src/ipc_address.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ipc_address.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include "err.hpp" - -#include <string> -#include <sstream> - -zmq::ipc_address_t::ipc_address_t () -{ - memset (&address, 0, sizeof (address)); -} - -zmq::ipc_address_t::ipc_address_t (const sockaddr *sa, socklen_t sa_len) -{ - zmq_assert(sa && sa_len > 0); - - memset (&address, 0, sizeof (address)); - if (sa->sa_family == AF_UNIX) { - memcpy(&address, sa, sa_len); - } -} - -zmq::ipc_address_t::~ipc_address_t () -{ -} - -int zmq::ipc_address_t::resolve (const char *path_) -{ - if (strlen (path_) >= sizeof (address.sun_path)) { - errno = ENAMETOOLONG; - return -1; - } -#if defined ZMQ_HAVE_LINUX - if (path_[0] == '@' && !path_[1]) { - errno = EINVAL; - return -1; - } -#endif - - address.sun_family = AF_UNIX; - strcpy (address.sun_path, path_); -#if defined ZMQ_HAVE_LINUX - /* Abstract sockets on Linux start with '\0' */ - if (path_[0] == '@') - *address.sun_path = '\0'; -#endif - return 0; -} - -int zmq::ipc_address_t::to_string (std::string &addr_) -{ - if (address.sun_family != AF_UNIX) { - addr_.clear (); - return -1; - } - - std::stringstream s; -#if !defined ZMQ_HAVE_LINUX - s << "ipc://" << address.sun_path; -#else - s << "ipc://"; - if (!address.sun_path[0] && address.sun_path[1]) - s << "@" << address.sun_path + 1; - else - s << address.sun_path; -#endif - addr_ = s.str (); - return 0; -} - -const sockaddr *zmq::ipc_address_t::addr () const -{ - return (sockaddr*) &address; -} - -socklen_t zmq::ipc_address_t::addrlen () const -{ -#if defined ZMQ_HAVE_LINUX - if (!address.sun_path[0] && address.sun_path[1]) - return (socklen_t) strlen(address.sun_path + 1) + sizeof (sa_family_t) + 1; -#endif - return (socklen_t) sizeof (address); -} - -#endif diff --git a/src/ipc_address.hpp b/src/ipc_address.hpp deleted file mode 100644 index 1f52746..0000000 --- a/src/ipc_address.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_IPC_ADDRESS_HPP_INCLUDED__ -#define __ZMQ_IPC_ADDRESS_HPP_INCLUDED__ - -#include <string> - -#include "platform.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include <sys/socket.h> -#include <sys/un.h> - -namespace zmq -{ - - class ipc_address_t - { - public: - - ipc_address_t (); - ipc_address_t (const sockaddr *sa, socklen_t sa_len); - ~ipc_address_t (); - - // This function sets up the address for UNIX domain transport. - int resolve (const char* path_); - - // The opposite to resolve() - int to_string (std::string &addr_); - - const sockaddr *addr () const; - socklen_t addrlen () const; - - private: - - struct sockaddr_un address; - - ipc_address_t (const ipc_address_t&); - const ipc_address_t &operator = (const ipc_address_t&); - }; - -} - -#endif - -#endif - - diff --git a/src/ipc_connecter.cpp b/src/ipc_connecter.cpp deleted file mode 100644 index 239d2be..0000000 --- a/src/ipc_connecter.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ipc_connecter.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include <new> -#include <string> - -#include "stream_engine.hpp" -#include "io_thread.hpp" -#include "platform.hpp" -#include "random.hpp" -#include "err.hpp" -#include "ip.hpp" -#include "address.hpp" -#include "ipc_address.hpp" -#include "session_base.hpp" - -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -zmq::ipc_connecter_t::ipc_connecter_t (class io_thread_t *io_thread_, - class session_base_t *session_, const options_t &options_, - const address_t *addr_, bool delayed_start_) : - own_t (io_thread_, options_), - io_object_t (io_thread_), - addr (addr_), - s (retired_fd), - handle_valid (false), - delayed_start (delayed_start_), - timer_started (false), - session (session_), - current_reconnect_ivl(options.reconnect_ivl) -{ - zmq_assert (addr); - zmq_assert (addr->protocol == "ipc"); - addr->to_string (endpoint); - socket = session-> get_socket(); -} - -zmq::ipc_connecter_t::~ipc_connecter_t () -{ - zmq_assert (!timer_started); - zmq_assert (!handle_valid); - zmq_assert (s == retired_fd); -} - -void zmq::ipc_connecter_t::process_plug () -{ - if (delayed_start) - add_reconnect_timer (); - else - start_connecting (); -} - -void zmq::ipc_connecter_t::process_term (int linger_) -{ - if (timer_started) { - cancel_timer (reconnect_timer_id); - timer_started = false; - } - - if (handle_valid) { - rm_fd (handle); - handle_valid = false; - } - - if (s != retired_fd) - close (); - - own_t::process_term (linger_); -} - -void zmq::ipc_connecter_t::in_event () -{ - // We are not polling for incomming data, so we are actually called - // because of error here. However, we can get error on out event as well - // on some platforms, so we'll simply handle both events in the same way. - out_event (); -} - -void zmq::ipc_connecter_t::out_event () -{ - fd_t fd = connect (); - rm_fd (handle); - handle_valid = false; - - // Handle the error condition by attempt to reconnect. - if (fd == retired_fd) { - close (); - add_reconnect_timer(); - return; - } - // Create the engine object for this connection. - stream_engine_t *engine = new (std::nothrow) - stream_engine_t (fd, options, endpoint); - alloc_assert (engine); - - // Attach the engine to the corresponding session object. - send_attach (session, engine); - - // Shut the connecter down. - terminate (); - - socket->event_connected (endpoint, fd); -} - -void zmq::ipc_connecter_t::timer_event (int id_) -{ - zmq_assert (id_ == reconnect_timer_id); - timer_started = false; - start_connecting (); -} - -void zmq::ipc_connecter_t::start_connecting () -{ - // Open the connecting socket. - int rc = open (); - - // Connect may succeed in synchronous manner. - if (rc == 0) { - handle = add_fd (s); - handle_valid = true; - out_event (); - } - - // Connection establishment may be delayed. Poll for its completion. - else - if (rc == -1 && errno == EINPROGRESS) { - handle = add_fd (s); - handle_valid = true; - set_pollout (handle); - socket->event_connect_delayed (endpoint, zmq_errno()); - } - - // Handle any other error condition by eventual reconnect. - else { - if (s != retired_fd) - close (); - add_reconnect_timer (); - } -} - -void zmq::ipc_connecter_t::add_reconnect_timer() -{ - int rc_ivl = get_new_reconnect_ivl(); - add_timer (rc_ivl, reconnect_timer_id); - socket->event_connect_retried (endpoint, rc_ivl); - timer_started = true; -} - -int zmq::ipc_connecter_t::get_new_reconnect_ivl () -{ - // The new interval is the current interval + random value. - int this_interval = current_reconnect_ivl + - (generate_random () % options.reconnect_ivl); - - // Only change the current reconnect interval if the maximum reconnect - // interval was set and if it's larger than the reconnect interval. - if (options.reconnect_ivl_max > 0 && - options.reconnect_ivl_max > options.reconnect_ivl) { - - // Calculate the next interval - current_reconnect_ivl = current_reconnect_ivl * 2; - if(current_reconnect_ivl >= options.reconnect_ivl_max) { - current_reconnect_ivl = options.reconnect_ivl_max; - } - } - return this_interval; -} - -int zmq::ipc_connecter_t::open () -{ - zmq_assert (s == retired_fd); - - // Create the socket. - s = open_socket (AF_UNIX, SOCK_STREAM, 0); - if (s == -1) - return -1; - - // Set the non-blocking flag. - unblock_socket (s); - - // Connect to the remote peer. - int rc = ::connect ( - s, addr->resolved.ipc_addr->addr (), - addr->resolved.ipc_addr->addrlen ()); - - // Connect was successfull immediately. - if (rc == 0) - return 0; - - // Translate other error codes indicating asynchronous connect has been - // launched to a uniform EINPROGRESS. - if (rc == -1 && errno == EINTR) { - errno = EINPROGRESS; - return -1; - } - - // Forward the error. - return -1; -} - -int zmq::ipc_connecter_t::close () -{ - zmq_assert (s != retired_fd); - int rc = ::close (s); - errno_assert (rc == 0); - socket->event_closed (endpoint, s); - s = retired_fd; - return 0; -} - -zmq::fd_t zmq::ipc_connecter_t::connect () -{ - // Following code should handle both Berkeley-derived socket - // implementations and Solaris. - int err = 0; -#if defined ZMQ_HAVE_HPUX - int len = sizeof (err); -#else - socklen_t len = sizeof (err); -#endif - int rc = getsockopt (s, SOL_SOCKET, SO_ERROR, (char*) &err, &len); - if (rc == -1) - err = errno; - if (err != 0) { - - // Assert if the error was caused by 0MQ bug. - // Networking problems are OK. No need to assert. - errno = err; - errno_assert (errno == ECONNREFUSED || errno == ECONNRESET || - errno == ETIMEDOUT || errno == EHOSTUNREACH || - errno == ENETUNREACH || errno == ENETDOWN); - - return retired_fd; - } - - fd_t result = s; - s = retired_fd; - return result; -} - -#endif - diff --git a/src/ipc_connecter.hpp b/src/ipc_connecter.hpp deleted file mode 100644 index ff2f31d..0000000 --- a/src/ipc_connecter.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __IPC_CONNECTER_HPP_INCLUDED__ -#define __IPC_CONNECTER_HPP_INCLUDED__ - -#include "platform.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include "fd.hpp" -#include "own.hpp" -#include "stdint.hpp" -#include "io_object.hpp" - -namespace zmq -{ - - class io_thread_t; - class session_base_t; - struct address_t; - - class ipc_connecter_t : public own_t, public io_object_t - { - public: - - // If 'delayed_start' is true connecter first waits for a while, - // then starts connection process. - ipc_connecter_t (zmq::io_thread_t *io_thread_, - zmq::session_base_t *session_, const options_t &options_, - const address_t *addr_, bool delayed_start_); - ~ipc_connecter_t (); - - private: - - // ID of the timer used to delay the reconnection. - enum {reconnect_timer_id = 1}; - - // Handlers for incoming commands. - void process_plug (); - void process_term (int linger_); - - // Handlers for I/O events. - void in_event (); - void out_event (); - void timer_event (int id_); - - // Internal function to start the actual connection establishment. - void start_connecting (); - - // Internal function to add a reconnect timer - void add_reconnect_timer(); - - // Internal function to return a reconnect backoff delay. - // Will modify the current_reconnect_ivl used for next call - // Returns the currently used interval - int get_new_reconnect_ivl (); - - // Open IPC connecting socket. Returns -1 in case of error, - // 0 if connect was successfull immediately. Returns -1 with - // EAGAIN errno if async connect was launched. - int open (); - - // Close the connecting socket. - int close (); - - // Get the file descriptor of newly created connection. Returns - // retired_fd if the connection was unsuccessfull. - fd_t connect (); - - // Address to connect to. Owned by session_base_t. - const address_t *addr; - - // Underlying socket. - fd_t s; - - // Handle corresponding to the listening socket. - handle_t handle; - - // If true file descriptor is registered with the poller and 'handle' - // contains valid value. - bool handle_valid; - - // If true, connecter is waiting a while before trying to connect. - const bool delayed_start; - - // True iff a timer has been started. - bool timer_started; - - // Reference to the session we belong to. - zmq::session_base_t *session; - - // Current reconnect ivl, updated for backoff strategy - int current_reconnect_ivl; - - // String representation of endpoint to connect to - std::string endpoint; - - // Socket - zmq::socket_base_t *socket; - - ipc_connecter_t (const ipc_connecter_t&); - const ipc_connecter_t &operator = (const ipc_connecter_t&); - }; - -} - -#endif - -#endif - diff --git a/src/ipc_listener.cpp b/src/ipc_listener.cpp deleted file mode 100644 index b102da6..0000000 --- a/src/ipc_listener.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ipc_listener.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include <new> - -#include <string.h> - -#include "stream_engine.hpp" -#include "ipc_address.hpp" -#include "io_thread.hpp" -#include "session_base.hpp" -#include "config.hpp" -#include "err.hpp" -#include "ip.hpp" -#include "socket_base.hpp" - -#include <unistd.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <sys/un.h> - -zmq::ipc_listener_t::ipc_listener_t (io_thread_t *io_thread_, - socket_base_t *socket_, const options_t &options_) : - own_t (io_thread_, options_), - io_object_t (io_thread_), - has_file (false), - s (retired_fd), - socket (socket_) -{ -} - -zmq::ipc_listener_t::~ipc_listener_t () -{ - zmq_assert (s == retired_fd); -} - -void zmq::ipc_listener_t::process_plug () -{ - // Start polling for incoming connections. - handle = add_fd (s); - set_pollin (handle); -} - -void zmq::ipc_listener_t::process_term (int linger_) -{ - rm_fd (handle); - close (); - own_t::process_term (linger_); -} - -void zmq::ipc_listener_t::in_event () -{ - fd_t fd = accept (); - - // If connection was reset by the peer in the meantime, just ignore it. - // TODO: Handle specific errors like ENFILE/EMFILE etc. - if (fd == retired_fd) { - socket->event_accept_failed (endpoint, zmq_errno()); - return; - } - - // Create the engine object for this connection. - stream_engine_t *engine = new (std::nothrow) - stream_engine_t (fd, options, endpoint); - alloc_assert (engine); - - // Choose I/O thread to run connecter in. Given that we are already - // running in an I/O thread, there must be at least one available. - io_thread_t *io_thread = choose_io_thread (options.affinity); - zmq_assert (io_thread); - - // Create and launch a session object. - session_base_t *session = session_base_t::create (io_thread, false, socket, - options, NULL); - errno_assert (session); - session->inc_seqnum (); - launch_child (session); - send_attach (session, engine, false); - socket->event_accepted (endpoint, fd); -} - -int zmq::ipc_listener_t::get_address (std::string &addr_) -{ - struct sockaddr_storage ss; -#ifdef ZMQ_HAVE_HPUX - int sl = sizeof (ss); -#else - socklen_t sl = sizeof (ss); -#endif - int rc = getsockname (s, (sockaddr *) &ss, &sl); - if (rc != 0) { - addr_.clear (); - return rc; - } - - ipc_address_t addr ((struct sockaddr *) &ss, sl); - return addr.to_string (addr_); -} - -int zmq::ipc_listener_t::set_address (const char *addr_) -{ - // Create addr on stack for auto-cleanup - std::string addr (addr_); - - // Allow wildcard file - if (addr[0] == '*') { - char *tmpstr = tempnam (NULL, NULL); - addr.assign (tmpstr); - free (tmpstr); - } - - // Get rid of the file associated with the UNIX domain socket that - // may have been left behind by the previous run of the application. - ::unlink (addr.c_str()); - filename.clear (); - - // Initialise the address structure. - ipc_address_t address; - int rc = address.resolve (addr.c_str()); - if (rc != 0) - return -1; - - // Create a listening socket. - s = open_socket (AF_UNIX, SOCK_STREAM, 0); - if (s == -1) - return -1; - - address.to_string (endpoint); - - // Bind the socket to the file path. - rc = bind (s, address.addr (), address.addrlen ()); - if (rc != 0) - goto error; - - filename.assign (addr.c_str()); - has_file = true; - - // Listen for incoming connections. - rc = listen (s, options.backlog); - if (rc != 0) - goto error; - - socket->event_listening (endpoint, s); - return 0; - -error: - int err = errno; - close (); - errno = err; - return -1; -} - -int zmq::ipc_listener_t::close () -{ - zmq_assert (s != retired_fd); - int rc = ::close (s); - errno_assert (rc == 0); - - s = retired_fd; - - // If there's an underlying UNIX domain socket, get rid of the file it - // is associated with. - if (has_file && !filename.empty ()) { - rc = ::unlink(filename.c_str ()); - if (rc != 0) { - socket->event_close_failed (endpoint, zmq_errno()); - return -1; - } - } - - socket->event_closed (endpoint, s); - return 0; -} - -zmq::fd_t zmq::ipc_listener_t::accept () -{ - // Accept one connection and deal with different failure modes. - // The situation where connection cannot be accepted due to insufficient - // resources is considered valid and treated by ignoring the connection. - zmq_assert (s != retired_fd); - fd_t sock = ::accept (s, NULL, NULL); - if (sock == -1) { - errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINTR || errno == ECONNABORTED || errno == EPROTO || - errno == ENFILE); - return retired_fd; - } - return sock; -} - -#endif diff --git a/src/ipc_listener.hpp b/src/ipc_listener.hpp deleted file mode 100644 index c022829..0000000 --- a/src/ipc_listener.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_IPC_LISTENER_HPP_INCLUDED__ -#define __ZMQ_IPC_LISTENER_HPP_INCLUDED__ - -#include "platform.hpp" - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - -#include <string> - -#include "fd.hpp" -#include "own.hpp" -#include "stdint.hpp" -#include "io_object.hpp" - -namespace zmq -{ - - class io_thread_t; - class socket_base_t; - - class ipc_listener_t : public own_t, public io_object_t - { - public: - - ipc_listener_t (zmq::io_thread_t *io_thread_, - zmq::socket_base_t *socket_, const options_t &options_); - ~ipc_listener_t (); - - // Set address to listen on. - int set_address (const char *addr_); - - // Get the bound address for use with wildcards - int get_address (std::string &addr_); - - private: - - // Handlers for incoming commands. - void process_plug (); - void process_term (int linger_); - - // Handlers for I/O events. - void in_event (); - - // Close the listening socket. - int close (); - - // Accept the new connection. Returns the file descriptor of the - // newly created connection. The function may return retired_fd - // if the connection was dropped while waiting in the listen backlog. - fd_t accept (); - - // True, if the undelying file for UNIX domain socket exists. - bool has_file; - - // Name of the file associated with the UNIX domain address. - std::string filename; - - // Underlying socket. - fd_t s; - - // Handle corresponding to the listening socket. - handle_t handle; - - // Socket the listerner belongs to. - zmq::socket_base_t *socket; - - // String representation of endpoint to bind to - std::string endpoint; - - ipc_listener_t (const ipc_listener_t&); - const ipc_listener_t &operator = (const ipc_listener_t&); - }; - -} - -#endif - -#endif - diff --git a/src/kqueue.cpp b/src/kqueue.cpp deleted file mode 100644 index 8ecf813..0000000 --- a/src/kqueue.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "kqueue.hpp" -#if defined ZMQ_USE_KQUEUE - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/event.h> -#include <stdlib.h> -#include <unistd.h> -#include <algorithm> -#include <new> - -#include "kqueue.hpp" -#include "err.hpp" -#include "config.hpp" -#include "i_poll_events.hpp" -#include "likely.hpp" - -// NetBSD defines (struct kevent).udata as intptr_t, everyone else -// as void *. -#if defined ZMQ_HAVE_NETBSD -#define kevent_udata_t intptr_t -#else -#define kevent_udata_t void * -#endif - -zmq::kqueue_t::kqueue_t () : - stopping (false) -{ - // Create event queue - kqueue_fd = kqueue (); - errno_assert (kqueue_fd != -1); -#ifdef HAVE_FORK - pid = getpid(); -#endif -} - -zmq::kqueue_t::~kqueue_t () -{ - worker.stop (); - close (kqueue_fd); -} - -void zmq::kqueue_t::kevent_add (fd_t fd_, short filter_, void *udata_) -{ - struct kevent ev; - - EV_SET (&ev, fd_, filter_, EV_ADD, 0, 0, (kevent_udata_t)udata_); - int rc = kevent (kqueue_fd, &ev, 1, NULL, 0, NULL); - errno_assert (rc != -1); -} - -void zmq::kqueue_t::kevent_delete (fd_t fd_, short filter_) -{ - struct kevent ev; - - EV_SET (&ev, fd_, filter_, EV_DELETE, 0, 0, 0); - int rc = kevent (kqueue_fd, &ev, 1, NULL, 0, NULL); - errno_assert (rc != -1); -} - -zmq::kqueue_t::handle_t zmq::kqueue_t::add_fd (fd_t fd_, - i_poll_events *reactor_) -{ - poll_entry_t *pe = new (std::nothrow) poll_entry_t; - alloc_assert (pe); - - pe->fd = fd_; - pe->flag_pollin = 0; - pe->flag_pollout = 0; - pe->reactor = reactor_; - - adjust_load (1); - - return pe; -} - -void zmq::kqueue_t::rm_fd (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - if (pe->flag_pollin) - kevent_delete (pe->fd, EVFILT_READ); - if (pe->flag_pollout) - kevent_delete (pe->fd, EVFILT_WRITE); - pe->fd = retired_fd; - retired.push_back (pe); - - adjust_load (-1); -} - -void zmq::kqueue_t::set_pollin (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - if (likely (!pe->flag_pollin)) { - pe->flag_pollin = true; - kevent_add (pe->fd, EVFILT_READ, pe); - } -} - -void zmq::kqueue_t::reset_pollin (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - if (likely (pe->flag_pollin)) { - pe->flag_pollin = false; - kevent_delete (pe->fd, EVFILT_READ); - } -} - -void zmq::kqueue_t::set_pollout (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - if (likely (!pe->flag_pollout)) { - pe->flag_pollout = true; - kevent_add (pe->fd, EVFILT_WRITE, pe); - } -} - -void zmq::kqueue_t::reset_pollout (handle_t handle_) -{ - poll_entry_t *pe = (poll_entry_t*) handle_; - if (likely (pe->flag_pollout)) { - pe->flag_pollout = false; - kevent_delete (pe->fd, EVFILT_WRITE); - } -} - -void zmq::kqueue_t::start () -{ - worker.start (worker_routine, this); -} - -void zmq::kqueue_t::stop () -{ - stopping = true; -} - -int zmq::kqueue_t::max_fds () -{ - return -1; -} - -void zmq::kqueue_t::loop () -{ - while (!stopping) { - - // Execute any due timers. - int timeout = (int) execute_timers (); - - // Wait for events. - struct kevent ev_buf [max_io_events]; - timespec ts = {timeout / 1000, (timeout % 1000) * 1000000}; - int n = kevent (kqueue_fd, NULL, 0, &ev_buf [0], max_io_events, - timeout ? &ts: NULL); -#ifdef HAVE_FORK - if (unlikely(pid != getpid())) { - //printf("zmq::kqueue_t::loop aborting on forked child %d\n", (int)getpid()); - // simply exit the loop in a forked process. - return; - } -#endif - if (n == -1) { - errno_assert (errno == EINTR); - continue; - } - - for (int i = 0; i < n; i ++) { - poll_entry_t *pe = (poll_entry_t*) ev_buf [i].udata; - - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].flags & EV_EOF) - pe->reactor->in_event (); - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].filter == EVFILT_WRITE) - pe->reactor->out_event (); - if (pe->fd == retired_fd) - continue; - if (ev_buf [i].filter == EVFILT_READ) - pe->reactor->in_event (); - } - - // Destroy retired event sources. - for (retired_t::iterator it = retired.begin (); it != retired.end (); - ++it) - delete *it; - retired.clear (); - } -} - -void zmq::kqueue_t::worker_routine (void *arg_) -{ - ((kqueue_t*) arg_)->loop (); -} - -#endif diff --git a/src/kqueue.hpp b/src/kqueue.hpp deleted file mode 100644 index 20d256c..0000000 --- a/src/kqueue.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_KQUEUE_HPP_INCLUDED__ -#define __ZMQ_KQUEUE_HPP_INCLUDED__ - -// poller.hpp decides which polling mechanism to use. -#include "poller.hpp" -#if defined ZMQ_USE_KQUEUE - -#include <vector> -#include <unistd.h> - -#include "fd.hpp" -#include "thread.hpp" -#include "poller_base.hpp" - -namespace zmq -{ - - struct i_poll_events; - - // Implements socket polling mechanism using the BSD-specific - // kqueue interface. - - class kqueue_t : public poller_base_t - { - public: - - typedef void* handle_t; - - kqueue_t (); - ~kqueue_t (); - - // "poller" concept. - handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void start (); - void stop (); - - static int max_fds (); - - private: - - // Main worker thread routine. - static void worker_routine (void *arg_); - - // Main event loop. - void loop (); - - // File descriptor referring to the kernel event queue. - fd_t kqueue_fd; - - // Adds the event to the kqueue. - void kevent_add (fd_t fd_, short filter_, void *udata_); - - // Deletes the event from the kqueue. - void kevent_delete (fd_t fd_, short filter_); - - struct poll_entry_t - { - fd_t fd; - bool flag_pollin; - bool flag_pollout; - zmq::i_poll_events *reactor; - }; - - // List of retired event sources. - typedef std::vector <poll_entry_t*> retired_t; - retired_t retired; - - // If true, thread is in the process of shutting down. - bool stopping; - - // Handle of the physical thread doing the I/O work. - thread_t worker; - - kqueue_t (const kqueue_t&); - const kqueue_t &operator = (const kqueue_t&); - -#ifdef HAVE_FORK - // the process that created this context. Used to detect forking. - pid_t pid; -#endif - }; - - typedef kqueue_t poller_t; - -} - -#endif - -#endif diff --git a/src/lb.cpp b/src/lb.cpp deleted file mode 100644 index 213bdfb..0000000 --- a/src/lb.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "lb.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::lb_t::lb_t () : - active (0), - current (0), - more (false), - dropping (false) -{ -} - -zmq::lb_t::~lb_t () -{ - zmq_assert (pipes.empty ()); -} - -void zmq::lb_t::attach (pipe_t *pipe_) -{ - pipes.push_back (pipe_); - activated (pipe_); -} - -void zmq::lb_t::pipe_terminated (pipe_t *pipe_) -{ - pipes_t::size_type index = pipes.index (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 == current && more) - dropping = true; - - // Remove the pipe from the list; adjust number of active pipes - // accordingly. - if (index < active) { - active--; - pipes.swap (index, active); - if (current == active) - current = 0; - } - pipes.erase (pipe_); -} - -void zmq::lb_t::activated (pipe_t *pipe_) -{ - // Move the pipe to the list of active pipes. - pipes.swap (pipes.index (pipe_), active); - active++; -} - -int zmq::lb_t::send (msg_t *msg_) -{ - return sendpipe (msg_, NULL); -} - -int zmq::lb_t::sendpipe (msg_t *msg_, pipe_t **pipe_) -{ - // Drop the message if required. If we are at the end of the message - // switch back to non-dropping mode. - if (dropping) { - - more = msg_->flags () & msg_t::more ? true : false; - dropping = more; - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - return 0; - } - - while (active > 0) { - if (pipes [current]->write (msg_)) - { - if (pipe_) - *pipe_ = pipes [current]; - break; - } - - zmq_assert (!more); - active--; - if (current < active) - pipes.swap (current, active); - else - current = 0; - } - - // If there are no pipes we cannot send the message. - if (active == 0) { - errno = EAGAIN; - return -1; - } - - // If it's final part of the message we can flush it downstream and - // continue round-robining (load balance). - more = msg_->flags () & msg_t::more? true: false; - if (!more) { - pipes [current]->flush (); - current = (current + 1) % active; - } - - // Detach the message from the data buffer. - int rc = msg_->init (); - errno_assert (rc == 0); - - return 0; -} - -bool zmq::lb_t::has_out () -{ - // If one part of the message was already written we can definitely - // write the rest of the message. - if (more) - return true; - - while (active > 0) { - - // Check whether a pipe has room for another message. - if (pipes [current]->check_write ()) - return true; - - // Deactivate the pipe. - active--; - pipes.swap (current, active); - if (current == active) - current = 0; - } - - return false; -} diff --git a/src/lb.hpp b/src/lb.hpp deleted file mode 100644 index 6904c89..0000000 --- a/src/lb.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_LB_HPP_INCLUDED__ -#define __ZMQ_LB_HPP_INCLUDED__ - -#include "array.hpp" -#include "pipe.hpp" - -namespace zmq -{ - - // This class manages a set of outbound pipes. On send it load balances - // messages fairly among the pipes. - - class lb_t - { - public: - - lb_t (); - ~lb_t (); - - void attach (pipe_t *pipe_); - void activated (pipe_t *pipe_); - void pipe_terminated (pipe_t *pipe_); - - int send (msg_t *msg_); - - // Sends a message and stores the pipe that was used in pipe_. - // It is possible for this function to return success but keep pipe_ - // unset if the rest of a multipart message to a terminated pipe is - // being dropped. For the first frame, this will never happen. - int sendpipe (msg_t *msg_, pipe_t **pipe_); - - bool has_out (); - - private: - - // List of outbound pipes. - typedef array_t <pipe_t, 2> pipes_t; - pipes_t pipes; - - // Number of active pipes. All the active pipes are located at the - // beginning of the pipes array. - pipes_t::size_type active; - - // Points to the last pipe that the most recent message was sent to. - pipes_t::size_type current; - - // True if last we are in the middle of a multipart message. - bool more; - - // True if we are dropping current message. - bool dropping; - - lb_t (const lb_t&); - const lb_t &operator = (const lb_t&); - }; - -} - -#endif diff --git a/src/libzmq.pc.in b/src/libzmq.pc.in deleted file mode 100644 index ba155a3..0000000 --- a/src/libzmq.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libzmq -Description: 0MQ c++ library -Version: @VERSION@ -Libs: -L${libdir} -lzmq -Cflags: -I${includedir} diff --git a/src/libzmq.vers b/src/libzmq.vers deleted file mode 100644 index 9a2d415..0000000 --- a/src/libzmq.vers +++ /dev/null @@ -1,4 +0,0 @@ -{ - global: zmq_*; - local: *; -}; diff --git a/src/likely.hpp b/src/likely.hpp deleted file mode 100644 index fb189f0..0000000 --- a/src/likely.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_LIKELY_HPP_INCLUDED__ -#define __ZMQ_LIKELY_HPP_INCLUDED__ - -#if defined __GNUC__ -#define likely(x) __builtin_expect ((x), 1) -#define unlikely(x) __builtin_expect ((x), 0) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - - -#endif diff --git a/src/mailbox.cpp b/src/mailbox.cpp deleted file mode 100644 index d1fd065..0000000 --- a/src/mailbox.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "mailbox.hpp" -#include "err.hpp" - -zmq::mailbox_t::mailbox_t () -{ - // Get the pipe into passive state. That way, if the users starts by - // polling on the associated file descriptor it will get woken up when - // new command is posted. - bool ok = cpipe.read (NULL); - zmq_assert (!ok); - active = false; -} - -zmq::mailbox_t::~mailbox_t () -{ - // TODO: Retrieve and deallocate commands inside the cpipe. - - // Work around problem that other threads might still be in our - // send() method, by waiting on the mutex before disappearing. - sync.lock (); - sync.unlock (); -} - -zmq::fd_t zmq::mailbox_t::get_fd () -{ - return signaler.get_fd (); -} - -void zmq::mailbox_t::send (const command_t &cmd_) -{ - sync.lock (); - cpipe.write (cmd_, false); - bool ok = cpipe.flush (); - sync.unlock (); - if (!ok) - signaler.send (); -} - -int zmq::mailbox_t::recv (command_t *cmd_, int timeout_) -{ - // Try to get the command straight away. - if (active) { - bool ok = cpipe.read (cmd_); - if (ok) - return 0; - - // If there are no more commands available, switch into passive state. - active = false; - signaler.recv (); - } - - // Wait for signal from the command sender. - int rc = signaler.wait (timeout_); - if (rc != 0 && (errno == EAGAIN || errno == EINTR)) - return -1; - - // We've got the signal. Now we can switch into active state. - active = true; - - // Get a command. - errno_assert (rc == 0); - bool ok = cpipe.read (cmd_); - zmq_assert (ok); - return 0; -} diff --git a/src/mailbox.hpp b/src/mailbox.hpp deleted file mode 100644 index 926ea84..0000000 --- a/src/mailbox.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_MAILBOX_HPP_INCLUDED__ -#define __ZMQ_MAILBOX_HPP_INCLUDED__ - -#include <stddef.h> - -#include "platform.hpp" -#include "signaler.hpp" -#include "fd.hpp" -#include "config.hpp" -#include "command.hpp" -#include "ypipe.hpp" -#include "mutex.hpp" - -namespace zmq -{ - - class mailbox_t - { - public: - - mailbox_t (); - ~mailbox_t (); - - fd_t get_fd (); - void send (const command_t &cmd_); - int recv (command_t *cmd_, int timeout_); - -#ifdef HAVE_FORK - // close the file descriptors in the signaller. This is used in a forked - // child process to close the file descriptors so that they do not interfere - // with the context in the parent process. - void forked() { signaler.forked(); } -#endif - - private: - - // The pipe to store actual commands. - typedef ypipe_t <command_t, command_pipe_granularity> cpipe_t; - cpipe_t cpipe; - - // Signaler to pass signals from writer thread to reader thread. - signaler_t signaler; - - // There's only one thread receiving from the mailbox, but there - // is arbitrary number of threads sending. Given that ypipe requires - // synchronised access on both of its endpoints, we have to synchronise - // the sending side. - mutex_t sync; - - // True if the underlying pipe is active, ie. when we are allowed to - // read commands from it. - bool active; - - // Disable copying of mailbox_t object. - mailbox_t (const mailbox_t&); - const mailbox_t &operator = (const mailbox_t&); - }; - -} - -#endif diff --git a/src/mechanism.cpp b/src/mechanism.cpp deleted file mode 100644 index 3c410f7..0000000 --- a/src/mechanism.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> - -#include "mechanism.hpp" -#include "options.hpp" -#include "msg.hpp" -#include "err.hpp" -#include "wire.hpp" - -zmq::mechanism_t::mechanism_t (const options_t &options_) : - options (options_) -{ -} - -zmq::mechanism_t::~mechanism_t () -{ -} - -void zmq::mechanism_t::set_peer_identity (const void *id_ptr, size_t id_size) -{ - identity = blob_t (static_cast <const unsigned char*> (id_ptr), id_size); -} - -void zmq::mechanism_t::peer_identity (msg_t *msg_) -{ - const int rc = msg_->init_size (identity.size ()); - errno_assert (rc == 0); - memcpy (msg_->data (), identity.data (), identity.size ()); - msg_->set_flags (msg_t::identity); -} - -const char *zmq::mechanism_t::socket_type_string (int socket_type) const -{ - static const char *names [] = {"PAIR", "PUB", "SUB", "REQ", "REP", - "DEALER", "ROUTER", "PULL", "PUSH", - "XPUB", "XSUB", "STREAM"}; - zmq_assert (socket_type >= 0 && socket_type <= 10); - return names [socket_type]; -} - -size_t zmq::mechanism_t::add_property (unsigned char *ptr, const char *name, - const void *value, size_t value_len) const -{ - const size_t name_len = strlen (name); - zmq_assert (name_len <= 255); - *ptr++ = static_cast <unsigned char> (name_len); - memcpy (ptr, name, name_len); - ptr += name_len; - zmq_assert (value_len <= 0x7FFFFFFF); - put_uint32 (ptr, static_cast <uint32_t> (value_len)); - ptr += 4; - memcpy (ptr, value, value_len); - - return 1 + name_len + 4 + value_len; -} - -int zmq::mechanism_t::parse_metadata (const unsigned char *ptr_, - size_t length_) -{ - size_t bytes_left = length_; - - while (bytes_left > 1) { - const size_t name_length = static_cast <size_t> (*ptr_); - ptr_ += 1; - bytes_left -= 1; - if (bytes_left < name_length) - break; - - const std::string name = std::string ((char *) ptr_, name_length); - ptr_ += name_length; - bytes_left -= name_length; - if (bytes_left < 4) - break; - - const size_t value_length = static_cast <size_t> (get_uint32 (ptr_)); - ptr_ += 4; - bytes_left -= 4; - if (bytes_left < value_length) - break; - - const uint8_t *value = ptr_; - ptr_ += value_length; - bytes_left -= value_length; - - if (name == "Identity" && options.recv_identity) - set_peer_identity (value, value_length); - else - if (name == "Socket-Type") { - const std::string socket_type ((char *) value, value_length); - if (!check_socket_type (socket_type)) { - errno = EINVAL; - return -1; - } - } - else { - const int rc = property (name, value, value_length); - if (rc == -1) - return -1; - } - } - if (bytes_left > 0) { - errno = EPROTO; - return -1; - } - return 0; -} - -int zmq::mechanism_t::property (const std::string name_, - const void *value_, size_t length_) -{ - // Default implementation does not check - // property values and returns 0 to signal success. - return 0; -} - -bool zmq::mechanism_t::check_socket_type (const std::string type_) const -{ - switch (options.type) { - case ZMQ_REQ: - return type_ == "REP" || type_ == "ROUTER"; - case ZMQ_REP: - return type_ == "REQ" || type_ == "DEALER"; - case ZMQ_DEALER: - return type_ == "REP" || type_ == "DEALER" || type_ == "ROUTER"; - case ZMQ_ROUTER: - return type_ == "REQ" || type_ == "DEALER" || type_ == "ROUTER"; - case ZMQ_PUSH: - return type_ == "PULL"; - case ZMQ_PULL: - return type_ == "PUSH"; - case ZMQ_PUB: - return type_ == "SUB" || type_ == "XSUB"; - case ZMQ_SUB: - return type_ == "PUB" || type_ == "XPUB"; - case ZMQ_XPUB: - return type_ == "SUB" || type_ == "XSUB"; - case ZMQ_XSUB: - return type_ == "PUB" || type_ == "XPUB"; - case ZMQ_PAIR: - return type_ == "PAIR"; - default: - break; - } - return false; -} diff --git a/src/mechanism.hpp b/src/mechanism.hpp deleted file mode 100644 index 8b73163..0000000 --- a/src/mechanism.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_MECHANISM_HPP_INCLUDED__ -#define __ZMQ_MECHANISM_HPP_INCLUDED__ - -#include "stdint.hpp" -#include "options.hpp" -#include "blob.hpp" - -namespace zmq -{ - - // Abstract class representing security mechanism. - // Different mechanism extedns this class. - - class msg_t; - - class mechanism_t - { - public: - - mechanism_t (const options_t &options_); - - virtual ~mechanism_t (); - - // Prepare next handshake command that is to be sent to the peer. - virtual int next_handshake_command (msg_t *msg_) = 0; - - // Process the handshake command received from the peer. - virtual int process_handshake_command (msg_t *msg_) = 0; - - virtual int encode (msg_t *msg_) { return 0; } - - virtual int decode (msg_t *msg_) { return 0; } - - // Notifies mechanism about availability of ZAP message. - virtual int zap_msg_available () { return 0; } - - // True iff the handshake stage is complete? - virtual bool is_handshake_complete () const = 0; - - void set_peer_identity (const void *id_ptr, size_t id_size); - - void peer_identity (msg_t *msg_); - - protected: - - // Only used to identify the socket for the Socket-Type - // property in the wire protocol. - const char *socket_type_string (int socket_type) const; - - size_t add_property (unsigned char *ptr, const char *name, - const void *value, size_t value_len) const; - - // Parses a metadata. - // Metadata consists of a list of properties consisting of - // name and value as size-specified strings. - // Returns 0 on success and -1 on error, in which case errno is set. - int parse_metadata (const unsigned char *ptr_, size_t length); - - // This is called by parse_property method whenever it - // parses a new property. The function should return 0 - // on success and -1 on error, in which case it should - // set errno. Signaling error prevents parser from - // parsing remaining data. - // Derived classes are supposed to override this - // method to handle custom processing. - virtual int property (const std::string name_, - const void *value_, size_t length_); - - options_t options; - - private: - - blob_t identity; - - // Returns true iff socket associated with the mechanism - // is compatible with a given socket type 'type_'. - bool check_socket_type (const std::string type_) const; - }; - -} - -#endif diff --git a/src/msg.cpp b/src/msg.cpp deleted file mode 100644 index f83ca05..0000000 --- a/src/msg.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "msg.hpp" -#include "../include/zmq.h" - -#include <string.h> -#include <stdlib.h> -#include <new> - -#include "stdint.hpp" -#include "likely.hpp" -#include "err.hpp" - -// Check whether the sizes of public representation of the message (zmq_msg_t) -// and private representation of the message (zmq::msg_t) match. -typedef char zmq_msg_size_check - [2 * ((sizeof (zmq::msg_t) == sizeof (zmq_msg_t)) != 0) - 1]; - -bool zmq::msg_t::check () -{ - return u.base.type >= type_min && u.base.type <= type_max; -} - -int zmq::msg_t::init () -{ - u.vsm.type = type_vsm; - u.vsm.flags = 0; - u.vsm.size = 0; - return 0; -} - -int zmq::msg_t::init_size (size_t size_) -{ - if (size_ <= max_vsm_size) { - u.vsm.type = type_vsm; - u.vsm.flags = 0; - u.vsm.size = (unsigned char) size_; - } - else { - u.lmsg.type = type_lmsg; - u.lmsg.flags = 0; - u.lmsg.content = - (content_t*) malloc (sizeof (content_t) + size_); - if (unlikely (!u.lmsg.content)) { - errno = ENOMEM; - return -1; - } - - u.lmsg.content->data = u.lmsg.content + 1; - u.lmsg.content->size = size_; - u.lmsg.content->ffn = NULL; - u.lmsg.content->hint = NULL; - new (&u.lmsg.content->refcnt) zmq::atomic_counter_t (); - } - return 0; -} - -int zmq::msg_t::init_data (void *data_, size_t size_, msg_free_fn *ffn_, - void *hint_) -{ - // If data is NULL and size is not 0, a segfault - // would occur once the data is accessed - assert (data_ != NULL || size_ == 0); - - // Initialize constant message if there's no need to deallocate - if(ffn_ == NULL) { - u.cmsg.type = type_cmsg; - u.cmsg.flags = 0; - u.cmsg.data = data_; - u.cmsg.size = size_; - } - else { - u.lmsg.type = type_lmsg; - u.lmsg.flags = 0; - u.lmsg.content = (content_t*) malloc (sizeof (content_t)); - if (!u.lmsg.content) { - errno = ENOMEM; - return -1; - } - - u.lmsg.content->data = data_; - u.lmsg.content->size = size_; - u.lmsg.content->ffn = ffn_; - u.lmsg.content->hint = hint_; - new (&u.lmsg.content->refcnt) zmq::atomic_counter_t (); - } - return 0; - -} - -int zmq::msg_t::init_delimiter () -{ - u.delimiter.type = type_delimiter; - u.delimiter.flags = 0; - return 0; -} - -int zmq::msg_t::close () -{ - // Check the validity of the message. - if (unlikely (!check ())) { - errno = EFAULT; - return -1; - } - - if (u.base.type == type_lmsg) { - - // If the content is not shared, or if it is shared and the reference - // count has dropped to zero, deallocate it. - if (!(u.lmsg.flags & msg_t::shared) || - !u.lmsg.content->refcnt.sub (1)) { - - // We used "placement new" operator to initialize the reference - // counter so we call the destructor explicitly now. - u.lmsg.content->refcnt.~atomic_counter_t (); - - if (u.lmsg.content->ffn) - u.lmsg.content->ffn (u.lmsg.content->data, - u.lmsg.content->hint); - free (u.lmsg.content); - } - } - - // Make the message invalid. - u.base.type = 0; - - return 0; - -} - -int zmq::msg_t::move (msg_t &src_) -{ - // Check the validity of the source. - if (unlikely (!src_.check ())) { - errno = EFAULT; - return -1; - } - - int rc = close (); - if (unlikely (rc < 0)) - return rc; - - *this = src_; - - rc = src_.init (); - if (unlikely (rc < 0)) - return rc; - - return 0; -} - -int zmq::msg_t::copy (msg_t &src_) -{ - // Check the validity of the source. - if (unlikely (!src_.check ())) { - errno = EFAULT; - return -1; - } - - int rc = close (); - if (unlikely (rc < 0)) - return rc; - - if (src_.u.base.type == type_lmsg) { - - // One reference is added to shared messages. Non-shared messages - // are turned into shared messages and reference count is set to 2. - if (src_.u.lmsg.flags & msg_t::shared) - src_.u.lmsg.content->refcnt.add (1); - else { - src_.u.lmsg.flags |= msg_t::shared; - src_.u.lmsg.content->refcnt.set (2); - } - } - - *this = src_; - - return 0; - -} - -void *zmq::msg_t::data () -{ - // Check the validity of the message. - zmq_assert (check ()); - - switch (u.base.type) { - case type_vsm: - return u.vsm.data; - case type_lmsg: - return u.lmsg.content->data; - case type_cmsg: - return u.cmsg.data; - default: - zmq_assert (false); - return NULL; - } -} - -size_t zmq::msg_t::size () -{ - // Check the validity of the message. - zmq_assert (check ()); - - switch (u.base.type) { - case type_vsm: - return u.vsm.size; - case type_lmsg: - return u.lmsg.content->size; - case type_cmsg: - return u.cmsg.size; - default: - zmq_assert (false); - return 0; - } -} - -unsigned char zmq::msg_t::flags () -{ - return u.base.flags; -} - -void zmq::msg_t::set_flags (unsigned char flags_) -{ - u.base.flags |= flags_; -} - -void zmq::msg_t::reset_flags (unsigned char flags_) -{ - u.base.flags &= ~flags_; -} - -bool zmq::msg_t::is_identity () const -{ - return (u.base.flags & identity) == identity; -} - -bool zmq::msg_t::is_delimiter () -{ - return u.base.type == type_delimiter; -} - -bool zmq::msg_t::is_vsm () -{ - return u.base.type == type_vsm; -} - -bool zmq::msg_t::is_cmsg () -{ - return u.base.type == type_cmsg; -} - -void zmq::msg_t::add_refs (int refs_) -{ - zmq_assert (refs_ >= 0); - - // No copies required. - if (!refs_) - return; - - // VSMs, CMSGS and delimiters can be copied straight away. The only - // message type that needs special care are long messages. - if (u.base.type == type_lmsg) { - if (u.lmsg.flags & msg_t::shared) - u.lmsg.content->refcnt.add (refs_); - else { - u.lmsg.content->refcnt.set (refs_ + 1); - u.lmsg.flags |= msg_t::shared; - } - } -} - -bool zmq::msg_t::rm_refs (int refs_) -{ - zmq_assert (refs_ >= 0); - - // No copies required. - if (!refs_) - return true; - - // If there's only one reference close the message. - if (u.base.type != type_lmsg || !(u.lmsg.flags & msg_t::shared)) { - close (); - return false; - } - - // The only message type that needs special care are long messages. - if (!u.lmsg.content->refcnt.sub (refs_)) { - // We used "placement new" operator to initialize the reference - // counter so we call the destructor explicitly now. - u.lmsg.content->refcnt.~atomic_counter_t (); - - if (u.lmsg.content->ffn) - u.lmsg.content->ffn (u.lmsg.content->data, u.lmsg.content->hint); - free (u.lmsg.content); - - return false; - } - - return true; -} - diff --git a/src/msg.hpp b/src/msg.hpp deleted file mode 100644 index fa3d76a..0000000 --- a/src/msg.hpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_MSG_HPP_INCLUDE__ -#define __ZMQ_MSG_HPP_INCLUDE__ - -#include <stddef.h> -#include <stdio.h> - -#include "config.hpp" -#include "atomic_counter.hpp" - -// Signature for free function to deallocate the message content. -// Note that it has to be declared as "C" so that it is the same as -// zmq_free_fn defined in zmq.h. -extern "C" -{ - typedef void (msg_free_fn) (void *data, void *hint); -} - -namespace zmq -{ - - // Note that this structure needs to be explicitly constructed - // (init functions) and destructed (close function). - - class msg_t - { - public: - - // Message flags. - enum - { - more = 1, // Followed by more parts - command = 2, // Command frame (see ZMTP spec) - identity = 64, - shared = 128 - }; - - bool check (); - int init (); - int init_size (size_t size_); - int init_data (void *data_, size_t size_, msg_free_fn *ffn_, - void *hint_); - int init_delimiter (); - int close (); - int move (msg_t &src_); - int copy (msg_t &src_); - void *data (); - size_t size (); - unsigned char flags (); - void set_flags (unsigned char flags_); - void reset_flags (unsigned char flags_); - bool is_identity () const; - bool is_delimiter (); - bool is_vsm (); - bool is_cmsg (); - - // After calling this function you can copy the message in POD-style - // refs_ times. No need to call copy. - void add_refs (int refs_); - - // Removes references previously added by add_refs. If the number of - // references drops to 0, the message is closed and false is returned. - bool rm_refs (int refs_); - - private: - - // Size in bytes of the largest message that is still copied around - // rather than being reference-counted. - enum {max_vsm_size = 29}; - - // Shared message buffer. Message data are either allocated in one - // continuous block along with this structure - thus avoiding one - // malloc/free pair or they are stored in used-supplied memory. - // In the latter case, ffn member stores pointer to the function to be - // used to deallocate the data. If the buffer is actually shared (there - // are at least 2 references to it) refcount member contains number of - // references. - struct content_t - { - void *data; - size_t size; - msg_free_fn *ffn; - void *hint; - zmq::atomic_counter_t refcnt; - }; - - // Different message types. - enum type_t - { - type_min = 101, - // VSM messages store the content in the message itself - type_vsm = 101, - // LMSG messages store the content in malloc-ed memory - type_lmsg = 102, - // Delimiter messages are used in envelopes - type_delimiter = 103, - // CMSG messages point to constant data - type_cmsg = 104, - type_max = 104 - }; - - // Note that fields shared between different message types are not - // moved to tha parent class (msg_t). This way we ger tighter packing - // of the data. Shared fields can be accessed via 'base' member of - // the union. - union { - struct { - unsigned char unused [max_vsm_size + 1]; - unsigned char type; - unsigned char flags; - } base; - struct { - unsigned char data [max_vsm_size]; - unsigned char size; - unsigned char type; - unsigned char flags; - } vsm; - struct { - content_t *content; - unsigned char unused [max_vsm_size + 1 - sizeof (content_t*)]; - unsigned char type; - unsigned char flags; - } lmsg; - struct { - void* data; - size_t size; - unsigned char unused - [max_vsm_size + 1 - sizeof (void*) - sizeof (size_t)]; - unsigned char type; - unsigned char flags; - } cmsg; - struct { - unsigned char unused [max_vsm_size + 1]; - unsigned char type; - unsigned char flags; - } delimiter; - } u; - }; - -} - -#endif diff --git a/src/mtrie.cpp b/src/mtrie.cpp deleted file mode 100644 index c09e2d2..0000000 --- a/src/mtrie.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> - -#include <new> -#include <algorithm> - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "err.hpp" -#include "pipe.hpp" -#include "mtrie.hpp" - -zmq::mtrie_t::mtrie_t () : - pipes (0), - min (0), - count (0), - live_nodes (0) -{ -} - -zmq::mtrie_t::~mtrie_t () -{ - if (pipes) { - delete pipes; - pipes = 0; - } - - if (count == 1) { - zmq_assert (next.node); - delete next.node; - next.node = 0; - } - else - if (count > 1) { - for (unsigned short i = 0; i != count; ++i) - delete next.table [i]; - free (next.table); - } -} - -bool zmq::mtrie_t::add (unsigned char *prefix_, size_t size_, pipe_t *pipe_) -{ - return add_helper (prefix_, size_, pipe_); -} - -bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_, - pipe_t *pipe_) -{ - // We are at the node corresponding to the prefix. We are done. - if (!size_) { - bool result = !pipes; - if (!pipes) { - pipes = new (std::nothrow) pipes_t; - alloc_assert (pipes); - } - pipes->insert (pipe_); - return result; - } - - unsigned char c = *prefix_; - if (c < min || c >= min + count) { - - // The character is out of range of currently handled - // charcters. We have to extend the table. - if (!count) { - min = c; - count = 1; - next.node = NULL; - } - else - if (count == 1) { - unsigned char oldc = min; - mtrie_t *oldp = next.node; - count = (min < c ? c - min : min - c) + 1; - next.table = (mtrie_t**) - malloc (sizeof (mtrie_t*) * count); - alloc_assert (next.table); - for (unsigned short i = 0; i != count; ++i) - next.table [i] = 0; - min = std::min (min, c); - next.table [oldc - min] = oldp; - } - else - if (min < c) { - // The new character is above the current character range. - unsigned short old_count = count; - count = c - min + 1; - next.table = (mtrie_t**) realloc (next.table, - sizeof (mtrie_t*) * count); - alloc_assert (next.table); - for (unsigned short i = old_count; i != count; i++) - next.table [i] = NULL; - } - else { - // The new character is below the current character range. - unsigned short old_count = count; - count = (min + old_count) - c; - next.table = (mtrie_t**) realloc (next.table, - sizeof (mtrie_t*) * count); - alloc_assert (next.table); - memmove (next.table + min - c, next.table, - old_count * sizeof (mtrie_t*)); - for (unsigned short i = 0; i != min - c; i++) - next.table [i] = NULL; - min = c; - } - } - - // If next node does not exist, create one. - if (count == 1) { - if (!next.node) { - next.node = new (std::nothrow) mtrie_t; - alloc_assert (next.node); - ++live_nodes; - } - return next.node->add_helper (prefix_ + 1, size_ - 1, pipe_); - } - else { - if (!next.table [c - min]) { - next.table [c - min] = new (std::nothrow) mtrie_t; - alloc_assert (next.table [c - min]); - ++live_nodes; - } - return next.table [c - min]->add_helper (prefix_ + 1, size_ - 1, pipe_); - } -} - - -void zmq::mtrie_t::rm (pipe_t *pipe_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), - void *arg_) -{ - unsigned char *buff = NULL; - rm_helper (pipe_, &buff, 0, 0, func_, arg_); - free (buff); -} - -void zmq::mtrie_t::rm_helper (pipe_t *pipe_, unsigned char **buff_, - size_t buffsize_, size_t maxbuffsize_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), - void *arg_) -{ - // Remove the subscription from this node. - if (pipes && pipes->erase (pipe_) && pipes->empty ()) { - func_ (*buff_, buffsize_, arg_); - delete pipes; - pipes = 0; - } - - // Adjust the buffer. - if (buffsize_ >= maxbuffsize_) { - maxbuffsize_ = buffsize_ + 256; - *buff_ = (unsigned char*) realloc (*buff_, maxbuffsize_); - alloc_assert (*buff_); - } - - // If there are no subnodes in the trie, return. - if (count == 0) - return; - - // If there's one subnode (optimisation). - if (count == 1) { - (*buff_) [buffsize_] = min; - buffsize_++; - next.node->rm_helper (pipe_, buff_, buffsize_, maxbuffsize_, - func_, arg_); - - // Prune the node if it was made redundant by the removal - if (next.node->is_redundant ()) { - delete next.node; - next.node = 0; - count = 0; - --live_nodes; - zmq_assert (live_nodes == 0); - } - return; - } - - // If there are multiple subnodes. - // - // New min non-null character in the node table after the removal - unsigned char new_min = min + count - 1; - // New max non-null character in the node table after the removal - unsigned char new_max = min; - for (unsigned short c = 0; c != count; c++) { - (*buff_) [buffsize_] = min + c; - if (next.table [c]) { - next.table [c]->rm_helper (pipe_, buff_, buffsize_ + 1, - maxbuffsize_, func_, arg_); - - // Prune redundant nodes from the mtrie - if (next.table [c]->is_redundant ()) { - delete next.table [c]; - next.table [c] = 0; - - zmq_assert (live_nodes > 0); - --live_nodes; - } - else { - // The node is not redundant, so it's a candidate for being - // the new min/max node. - // - // We loop through the node array from left to right, so the - // first non-null, non-redundant node encountered is the new - // minimum index. Conversely, the last non-redundant, non-null - // node encountered is the new maximum index. - if (c + min < new_min) - new_min = c + min; - if (c + min > new_max) - new_max = c + min; - } - } - } - - zmq_assert (count > 1); - - // Free the node table if it's no longer used. - if (live_nodes == 0) { - free (next.table); - next.table = NULL; - count = 0; - } - // Compact the node table if possible - else - if (live_nodes == 1) { - // If there's only one live node in the table we can - // switch to using the more compact single-node - // representation - zmq_assert (new_min == new_max); - zmq_assert (new_min >= min && new_min < min + count); - mtrie_t *node = next.table [new_min - min]; - zmq_assert (node); - free (next.table); - next.node = node; - count = 1; - min = new_min; - } - else - if (new_min > min || new_max < min + count - 1) { - zmq_assert (new_max - new_min + 1 > 1); - - mtrie_t **old_table = next.table; - zmq_assert (new_min > min || new_max < min + count - 1); - zmq_assert (new_min >= min); - zmq_assert (new_max <= min + count - 1); - zmq_assert (new_max - new_min + 1 < count); - - count = new_max - new_min + 1; - next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); - alloc_assert (next.table); - - memmove (next.table, old_table + (new_min - min), - sizeof (mtrie_t*) * count); - free (old_table); - - min = new_min; - } -} - -bool zmq::mtrie_t::rm (unsigned char *prefix_, size_t size_, pipe_t *pipe_) -{ - return rm_helper (prefix_, size_, pipe_); -} - -bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_, - pipe_t *pipe_) -{ - if (!size_) { - if (pipes) { - pipes_t::size_type erased = pipes->erase (pipe_); - zmq_assert (erased == 1); - if (pipes->empty ()) { - delete pipes; - pipes = 0; - } - } - return !pipes; - } - - unsigned char c = *prefix_; - if (!count || c < min || c >= min + count) - return false; - - mtrie_t *next_node = - count == 1 ? next.node : next.table [c - min]; - - if (!next_node) - return false; - - bool ret = next_node->rm_helper (prefix_ + 1, size_ - 1, pipe_); - - if (next_node->is_redundant ()) { - delete next_node; - zmq_assert (count > 0); - - if (count == 1) { - next.node = 0; - count = 0; - --live_nodes; - zmq_assert (live_nodes == 0); - } - else { - next.table [c - min] = 0; - zmq_assert (live_nodes > 1); - --live_nodes; - - // Compact the table if possible - if (live_nodes == 1) { - // If there's only one live node in the table we can - // switch to using the more compact single-node - // representation - unsigned short i; - for (i = 0; i < count; ++i) - if (next.table [i]) - break; - - zmq_assert (i < count); - min += i; - count = 1; - mtrie_t *oldp = next.table [i]; - free (next.table); - next.node = oldp; - } - else - if (c == min) { - // We can compact the table "from the left" - unsigned short i; - for (i = 1; i < count; ++i) - if (next.table [i]) - break; - - zmq_assert (i < count); - min += i; - count -= i; - mtrie_t **old_table = next.table; - next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); - alloc_assert (next.table); - memmove (next.table, old_table + i, sizeof (mtrie_t*) * count); - free (old_table); - } - else - if (c == min + count - 1) { - // We can compact the table "from the right" - unsigned short i; - for (i = 1; i < count; ++i) - if (next.table [count - 1 - i]) - break; - - zmq_assert (i < count); - count -= i; - mtrie_t **old_table = next.table; - next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); - alloc_assert (next.table); - memmove (next.table, old_table, sizeof (mtrie_t*) * count); - free (old_table); - } - } - } - - return ret; -} - -void zmq::mtrie_t::match (unsigned char *data_, size_t size_, - void (*func_) (pipe_t *pipe_, void *arg_), void *arg_) -{ - mtrie_t *current = this; - while (true) { - - // Signal the pipes attached to this node. - if (current->pipes) { - for (pipes_t::iterator it = current->pipes->begin (); - it != current->pipes->end (); ++it) - func_ (*it, arg_); - } - - // If we are at the end of the message, there's nothing more to match. - if (!size_) - break; - - // If there are no subnodes in the trie, return. - if (current->count == 0) - break; - - // If there's one subnode (optimisation). - if (current->count == 1) { - if (data_ [0] != current->min) - break; - current = current->next.node; - data_++; - size_--; - continue; - } - - // If there are multiple subnodes. - if (data_ [0] < current->min || data_ [0] >= - current->min + current->count) - break; - if (!current->next.table [data_ [0] - current->min]) - break; - current = current->next.table [data_ [0] - current->min]; - data_++; - size_--; - } -} - -bool zmq::mtrie_t::is_redundant () const -{ - return !pipes && live_nodes == 0; -} diff --git a/src/mtrie.hpp b/src/mtrie.hpp deleted file mode 100644 index d6d52ba..0000000 --- a/src/mtrie.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_MTRIE_HPP_INCLUDED__ -#define __ZMQ_MTRIE_HPP_INCLUDED__ - -#include <stddef.h> -#include <set> - -#include "stdint.hpp" - -namespace zmq -{ - - class pipe_t; - - // Multi-trie. Each node in the trie is a set of pointers to pipes. - - class mtrie_t - { - public: - - mtrie_t (); - ~mtrie_t (); - - // Add key to the trie. Returns true if it's a new subscription - // rather than a duplicate. - bool add (unsigned char *prefix_, size_t size_, zmq::pipe_t *pipe_); - - // Remove all subscriptions for a specific peer from the trie. - // If there are no subscriptions left on some topics, invoke the - // supplied callback function. - void rm (zmq::pipe_t *pipe_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), - void *arg_); - - // Remove specific subscription from the trie. Return true is it was - // actually removed rather than de-duplicated. - bool rm (unsigned char *prefix_, size_t size_, zmq::pipe_t *pipe_); - - // Signal all the matching pipes. - void match (unsigned char *data_, size_t size_, - void (*func_) (zmq::pipe_t *pipe_, void *arg_), void *arg_); - - private: - - bool add_helper (unsigned char *prefix_, size_t size_, - zmq::pipe_t *pipe_); - void rm_helper (zmq::pipe_t *pipe_, unsigned char **buff_, - size_t buffsize_, size_t maxbuffsize_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), - void *arg_); - bool rm_helper (unsigned char *prefix_, size_t size_, - zmq::pipe_t *pipe_); - bool is_redundant () const; - - typedef std::set <zmq::pipe_t*> pipes_t; - pipes_t *pipes; - - unsigned char min; - unsigned short count; - unsigned short live_nodes; - union { - class mtrie_t *node; - class mtrie_t **table; - } next; - - mtrie_t (const mtrie_t&); - const mtrie_t &operator = (const mtrie_t&); - }; - -} - -#endif - diff --git a/src/mutex.hpp b/src/mutex.hpp deleted file mode 100644 index c72314d..0000000 --- a/src/mutex.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_MUTEX_HPP_INCLUDED__ -#define __ZMQ_MUTEX_HPP_INCLUDED__ - -#include "platform.hpp" -#include "err.hpp" - -// Mutex class encapsulates OS mutex in a platform-independent way. - -#ifdef ZMQ_HAVE_WINDOWS - -#include "windows.hpp" - -namespace zmq -{ - - class mutex_t - { - public: - inline mutex_t () - { - InitializeCriticalSection (&cs); - } - - inline ~mutex_t () - { - DeleteCriticalSection (&cs); - } - - inline void lock () - { - EnterCriticalSection (&cs); - } - - inline bool try_lock () - { - return (TryEnterCriticalSection (&cs)) ? true : false; - } - - inline void unlock () - { - LeaveCriticalSection (&cs); - } - - private: - - CRITICAL_SECTION cs; - - // Disable copy construction and assignment. - mutex_t (const mutex_t&); - void operator = (const mutex_t&); - }; - -} - -#else - -#include <pthread.h> - -namespace zmq -{ - - class mutex_t - { - public: - inline mutex_t () - { - int rc = pthread_mutex_init (&mutex, NULL); - posix_assert (rc); - } - - inline ~mutex_t () - { - int rc = pthread_mutex_destroy (&mutex); - posix_assert (rc); - } - - inline void lock () - { - int rc = pthread_mutex_lock (&mutex); - posix_assert (rc); - } - - inline bool try_lock () - { - int rc = pthread_mutex_trylock (&mutex); - if (rc == EBUSY) - return false; - - posix_assert (rc); - return true; - } - - inline void unlock () - { - int rc = pthread_mutex_unlock (&mutex); - posix_assert (rc); - } - - private: - - pthread_mutex_t mutex; - - // Disable copy construction and assignment. - mutex_t (const mutex_t&); - const mutex_t &operator = (const mutex_t&); - }; - -} - -#endif - - -namespace zmq -{ - struct scoped_lock_t - { - scoped_lock_t (mutex_t& mutex_) - : mutex (mutex_) - { - mutex.lock (); - } - - ~scoped_lock_t () - { - mutex.unlock (); - } - - private: - - mutex_t& mutex; - - // Disable copy construction and assignment. - scoped_lock_t (const scoped_lock_t&); - const scoped_lock_t &operator = (const scoped_lock_t&); - }; -} - -#endif diff --git a/src/null_mechanism.cpp b/src/null_mechanism.cpp deleted file mode 100644 index f4ea9e7..0000000 --- a/src/null_mechanism.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include <stddef.h> -#include <string.h> -#include <stdlib.h> - -#include "err.hpp" -#include "msg.hpp" -#include "session_base.hpp" -#include "wire.hpp" -#include "null_mechanism.hpp" - -zmq::null_mechanism_t::null_mechanism_t (session_base_t *session_, - const std::string &peer_address_, - const options_t &options_) : - mechanism_t (options_), - session (session_), - peer_address (peer_address_), - ready_command_sent (false), - ready_command_received (false), - zap_connected (false), - zap_request_sent (false), - zap_reply_received (false) -{ - // NULL mechanism only uses ZAP if there's a domain defined - // This prevents ZAP requests on naive sockets - if (options.zap_domain.size () > 0 - && session->zap_connect () == 0) - zap_connected = true; -} - -zmq::null_mechanism_t::~null_mechanism_t () -{ -} - -int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_) -{ - if (ready_command_sent) { - errno = EAGAIN; - return -1; - } - if (zap_connected && !zap_reply_received) { - if (zap_request_sent) { - errno = EAGAIN; - return -1; - } - send_zap_request (); - zap_request_sent = true; - const int rc = receive_and_process_zap_reply (); - if (rc != 0) - return -1; - zap_reply_received = true; - } - - unsigned char * const command_buffer = (unsigned char *) malloc (512); - alloc_assert (command_buffer); - - unsigned char *ptr = command_buffer; - - // Add mechanism string - memcpy (ptr, "\5READY", 6); - ptr += 6; - - // Add socket type property - const char *socket_type = socket_type_string (options.type); - ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type)); - - // Add identity property - if (options.type == ZMQ_REQ - || options.type == ZMQ_DEALER - || options.type == ZMQ_ROUTER) { - ptr += add_property (ptr, "Identity", - options.identity, options.identity_size); - } - - const size_t command_size = ptr - command_buffer; - const int rc = msg_->init_size (command_size); - errno_assert (rc == 0); - memcpy (msg_->data (), command_buffer, command_size); - free (command_buffer); - - ready_command_sent = true; - - return 0; -} - -int zmq::null_mechanism_t::process_handshake_command (msg_t *msg_) -{ - if (ready_command_received) { - errno = EPROTO; - return -1; - } - - const unsigned char *ptr = - static_cast <unsigned char *> (msg_->data ()); - size_t bytes_left = msg_->size (); - - if (bytes_left < 6 || memcmp (ptr, "\5READY", 6)) { - errno = EPROTO; - return -1; - } - - ptr += 6; - bytes_left -= 6; - - int rc = parse_metadata (ptr, bytes_left); - if (rc == 0) { - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - } - - ready_command_received = true; - - return rc; -} - -int zmq::null_mechanism_t::zap_msg_available () -{ - if (zap_reply_received) { - errno = EFSM; - return -1; - } - const int rc = receive_and_process_zap_reply (); - if (rc == 0) - zap_reply_received = true; - return rc; -} - -bool zmq::null_mechanism_t::is_handshake_complete () const -{ - return ready_command_received && ready_command_sent; -} - -void zmq::null_mechanism_t::send_zap_request () -{ - int rc; - msg_t msg; - - // Address delimiter frame - rc = msg.init (); - errno_assert (rc == 0); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Version frame - rc = msg.init_size (3); - errno_assert (rc == 0); - memcpy (msg.data (), "1.0", 3); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Request id frame - rc = msg.init_size (1); - errno_assert (rc == 0); - memcpy (msg.data (), "1", 1); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Domain frame - rc = msg.init_size (options.zap_domain.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Address frame - rc = msg.init_size (peer_address.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), peer_address.c_str (), peer_address.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Identity frame - rc = msg.init_size (options.identity_size); - errno_assert (rc == 0); - memcpy (msg.data (), options.identity, options.identity_size); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Mechanism frame - rc = msg.init_size (4); - errno_assert (rc == 0); - memcpy (msg.data (), "NULL", 4); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); -} - -int zmq::null_mechanism_t::receive_and_process_zap_reply () -{ - int rc = 0; - msg_t msg [7]; // ZAP reply consists of 7 frames - - // Initialize all reply frames - for (int i = 0; i < 7; i++) { - rc = msg [i].init (); - errno_assert (rc == 0); - } - - for (int i = 0; i < 7; i++) { - rc = session->read_zap_msg (&msg [i]); - if (rc == -1) - break; - if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) { - errno = EPROTO; - rc = -1; - break; - } - } - - if (rc != 0) - goto error; - - // Address delimiter frame - if (msg [0].size () > 0) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Version frame - if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Request id frame - if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Status code frame - if (msg [3].size () != 3 || memcmp (msg [3].data (), "200", 3)) { - rc = -1; - errno = EACCES; - goto error; - } - - // Process metadata frame - rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()), - msg [6].size ()); - -error: - for (int i = 0; i < 7; i++) { - const int rc2 = msg [i].close (); - errno_assert (rc2 == 0); - } - - return rc; -} diff --git a/src/null_mechanism.hpp b/src/null_mechanism.hpp deleted file mode 100644 index ad168e5..0000000 --- a/src/null_mechanism.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_NULL_MECHANISM_HPP_INCLUDED__ -#define __ZMQ_NULL_MECHANISM_HPP_INCLUDED__ - -#include "mechanism.hpp" -#include "options.hpp" - -namespace zmq -{ - - class msg_t; - class session_base_t; - - class null_mechanism_t : public mechanism_t - { - public: - - null_mechanism_t (session_base_t *session_, - const std::string &peer_address, - const options_t &options_); - virtual ~null_mechanism_t (); - - // mechanism implementation - virtual int next_handshake_command (msg_t *msg_); - virtual int process_handshake_command (msg_t *msg_); - virtual int zap_msg_available (); - virtual bool is_handshake_complete () const; - - private: - - session_base_t * const session; - - const std::string peer_address; - - bool ready_command_sent; - bool ready_command_received; - bool zap_connected; - bool zap_request_sent; - bool zap_reply_received; - - void send_zap_request (); - int receive_and_process_zap_reply (); - }; - -} - -#endif diff --git a/src/object.cpp b/src/object.cpp deleted file mode 100644 index e658b28..0000000 --- a/src/object.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> -#include <stdarg.h> - -#include "object.hpp" -#include "ctx.hpp" -#include "err.hpp" -#include "pipe.hpp" -#include "io_thread.hpp" -#include "session_base.hpp" -#include "socket_base.hpp" - -zmq::object_t::object_t (ctx_t *ctx_, uint32_t tid_) : - ctx (ctx_), - tid (tid_) -{ -} - -zmq::object_t::object_t (object_t *parent_) : - ctx (parent_->ctx), - tid (parent_->tid) -{ -} - -zmq::object_t::~object_t () -{ -} - -uint32_t zmq::object_t::get_tid () -{ - return tid; -} - -void zmq::object_t::set_tid(uint32_t id) -{ - tid = id; -} - -zmq::ctx_t *zmq::object_t::get_ctx () -{ - return ctx; -} - -void zmq::object_t::process_command (command_t &cmd_) -{ - switch (cmd_.type) { - - case command_t::activate_read: - process_activate_read (); - break; - - case command_t::activate_write: - process_activate_write (cmd_.args.activate_write.msgs_read); - break; - - case command_t::stop: - process_stop (); - break; - - case command_t::plug: - process_plug (); - process_seqnum (); - break; - - case command_t::own: - process_own (cmd_.args.own.object); - process_seqnum (); - break; - - case command_t::attach: - process_attach (cmd_.args.attach.engine); - process_seqnum (); - break; - - case command_t::bind: - process_bind (cmd_.args.bind.pipe); - process_seqnum (); - break; - - case command_t::hiccup: - process_hiccup (cmd_.args.hiccup.pipe); - break; - - case command_t::pipe_term: - process_pipe_term (); - break; - - case command_t::pipe_term_ack: - process_pipe_term_ack (); - break; - - case command_t::term_req: - process_term_req (cmd_.args.term_req.object); - break; - - case command_t::term: - process_term (cmd_.args.term.linger); - break; - - case command_t::term_ack: - process_term_ack (); - break; - - case command_t::reap: - process_reap (cmd_.args.reap.socket); - break; - - case command_t::reaped: - process_reaped (); - break; - - case command_t::inproc_connected: - process_seqnum (); - break; - - case command_t::done: - default: - zmq_assert (false); - } -} - -int zmq::object_t::register_endpoint (const char *addr_, endpoint_t &endpoint_) -{ - return ctx->register_endpoint (addr_, endpoint_); -} - -void zmq::object_t::unregister_endpoints (socket_base_t *socket_) -{ - return ctx->unregister_endpoints (socket_); -} - -zmq::endpoint_t zmq::object_t::find_endpoint (const char *addr_) -{ - return ctx->find_endpoint (addr_); -} - -void zmq::object_t::pend_connection (const char *addr_, pending_connection_t &pending_connection_) -{ - ctx->pend_connection (addr_, pending_connection_); -} - -void zmq::object_t::connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_) -{ - return ctx->connect_pending(addr_, bind_socket_); -} - -void zmq::object_t::destroy_socket (socket_base_t *socket_) -{ - ctx->destroy_socket (socket_); -} - -zmq::io_thread_t *zmq::object_t::choose_io_thread (uint64_t affinity_) -{ - return ctx->choose_io_thread (affinity_); -} - -void zmq::object_t::send_stop () -{ - // 'stop' command goes always from administrative thread to - // the current object. - command_t cmd; - cmd.destination = this; - cmd.type = command_t::stop; - ctx->send_command (tid, cmd); -} - -void zmq::object_t::send_plug (own_t *destination_, bool inc_seqnum_) -{ - if (inc_seqnum_) - destination_->inc_seqnum (); - - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::plug; - send_command (cmd); -} - -void zmq::object_t::send_own (own_t *destination_, own_t *object_) -{ - destination_->inc_seqnum (); - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::own; - cmd.args.own.object = object_; - send_command (cmd); -} - -void zmq::object_t::send_attach (session_base_t *destination_, - i_engine *engine_, bool inc_seqnum_) -{ - if (inc_seqnum_) - destination_->inc_seqnum (); - - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::attach; - cmd.args.attach.engine = engine_; - send_command (cmd); -} - -void zmq::object_t::send_bind (own_t *destination_, pipe_t *pipe_, - bool inc_seqnum_) -{ - if (inc_seqnum_) - destination_->inc_seqnum (); - - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::bind; - cmd.args.bind.pipe = pipe_; - send_command (cmd); -} - -void zmq::object_t::send_activate_read (pipe_t *destination_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::activate_read; - send_command (cmd); -} - -void zmq::object_t::send_activate_write (pipe_t *destination_, - uint64_t msgs_read_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::activate_write; - cmd.args.activate_write.msgs_read = msgs_read_; - send_command (cmd); -} - -void zmq::object_t::send_hiccup (pipe_t *destination_, void *pipe_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::hiccup; - cmd.args.hiccup.pipe = pipe_; - send_command (cmd); -} - -void zmq::object_t::send_pipe_term (pipe_t *destination_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::pipe_term; - send_command (cmd); -} - -void zmq::object_t::send_pipe_term_ack (pipe_t *destination_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::pipe_term_ack; - send_command (cmd); -} - -void zmq::object_t::send_term_req (own_t *destination_, - own_t *object_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::term_req; - cmd.args.term_req.object = object_; - send_command (cmd); -} - -void zmq::object_t::send_term (own_t *destination_, int linger_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::term; - cmd.args.term.linger = linger_; - send_command (cmd); -} - -void zmq::object_t::send_term_ack (own_t *destination_) -{ - command_t cmd; - cmd.destination = destination_; - cmd.type = command_t::term_ack; - send_command (cmd); -} - -void zmq::object_t::send_reap (class socket_base_t *socket_) -{ - command_t cmd; - cmd.destination = ctx->get_reaper (); - cmd.type = command_t::reap; - cmd.args.reap.socket = socket_; - send_command (cmd); -} - -void zmq::object_t::send_reaped () -{ - command_t cmd; - cmd.destination = ctx->get_reaper (); - cmd.type = command_t::reaped; - send_command (cmd); -} - -void zmq::object_t::send_inproc_connected (zmq::socket_base_t *socket_) -{ - command_t cmd; - cmd.destination = socket_; - cmd.type = command_t::inproc_connected; - send_command (cmd); -} - -void zmq::object_t::send_done () -{ - command_t cmd; - cmd.destination = NULL; - cmd.type = command_t::done; - ctx->send_command (ctx_t::term_tid, cmd); -} - -void zmq::object_t::process_stop () -{ - zmq_assert (false); -} - -void zmq::object_t::process_plug () -{ - zmq_assert (false); -} - -void zmq::object_t::process_own (own_t *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_attach (i_engine *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_bind (pipe_t *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_activate_read () -{ - zmq_assert (false); -} - -void zmq::object_t::process_activate_write (uint64_t) -{ - zmq_assert (false); -} - -void zmq::object_t::process_hiccup (void *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_pipe_term () -{ - zmq_assert (false); -} - -void zmq::object_t::process_pipe_term_ack () -{ - zmq_assert (false); -} - -void zmq::object_t::process_term_req (own_t *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_term (int) -{ - zmq_assert (false); -} - -void zmq::object_t::process_term_ack () -{ - zmq_assert (false); -} - -void zmq::object_t::process_reap (class socket_base_t *) -{ - zmq_assert (false); -} - -void zmq::object_t::process_reaped () -{ - zmq_assert (false); -} - -void zmq::object_t::process_seqnum () -{ - zmq_assert (false); -} - -void zmq::object_t::send_command (command_t &cmd_) -{ - ctx->send_command (cmd_.destination->get_tid (), cmd_); -} - diff --git a/src/object.hpp b/src/object.hpp deleted file mode 100644 index 7655c38..0000000 --- a/src/object.hpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_OBJECT_HPP_INCLUDED__ -#define __ZMQ_OBJECT_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - struct i_engine; - struct endpoint_t; - struct pending_connection_t; - struct command_t; - class ctx_t; - class pipe_t; - class socket_base_t; - class session_base_t; - class io_thread_t; - class own_t; - - // Base class for all objects that participate in inter-thread - // communication. - - class object_t - { - public: - - object_t (zmq::ctx_t *ctx_, uint32_t tid_); - object_t (object_t *parent_); - virtual ~object_t (); - - uint32_t get_tid (); - void set_tid(uint32_t id); - ctx_t *get_ctx (); - void process_command (zmq::command_t &cmd_); - void send_inproc_connected (zmq::socket_base_t *socket_); - void send_bind (zmq::own_t *destination_, zmq::pipe_t *pipe_, bool inc_seqnum_ = true); - - protected: - - // Using following function, socket is able to access global - // repository of inproc endpoints. - int register_endpoint (const char *addr_, zmq::endpoint_t &endpoint_); - void unregister_endpoints (zmq::socket_base_t *socket_); - zmq::endpoint_t find_endpoint (const char *addr_); - void pend_connection (const char *addr_, pending_connection_t &pending_connection_); - void connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_); - - void destroy_socket (zmq::socket_base_t *socket_); - - // Logs an message. - void log (const char *format_, ...); - - // Chooses least loaded I/O thread. - zmq::io_thread_t *choose_io_thread (uint64_t affinity_); - - // Derived object can use these functions to send commands - // to other objects. - void send_stop (); - void send_plug (zmq::own_t *destination_, - bool inc_seqnum_ = true); - void send_own (zmq::own_t *destination_, - zmq::own_t *object_); - void send_attach (zmq::session_base_t *destination_, - zmq::i_engine *engine_, bool inc_seqnum_ = true); - void send_activate_read (zmq::pipe_t *destination_); - void send_activate_write (zmq::pipe_t *destination_, - uint64_t msgs_read_); - void send_hiccup (zmq::pipe_t *destination_, void *pipe_); - void send_pipe_term (zmq::pipe_t *destination_); - void send_pipe_term_ack (zmq::pipe_t *destination_); - void send_term_req (zmq::own_t *destination_, - zmq::own_t *object_); - void send_term (zmq::own_t *destination_, int linger_); - void send_term_ack (zmq::own_t *destination_); - void send_reap (zmq::socket_base_t *socket_); - void send_reaped (); - void send_done (); - - // These handlers can be overloaded by the derived objects. They are - // called when command arrives from another thread. - virtual void process_stop (); - virtual void process_plug (); - virtual void process_own (zmq::own_t *object_); - virtual void process_attach (zmq::i_engine *engine_); - virtual void process_bind (zmq::pipe_t *pipe_); - virtual void process_activate_read (); - virtual void process_activate_write (uint64_t msgs_read_); - virtual void process_hiccup (void *pipe_); - virtual void process_pipe_term (); - virtual void process_pipe_term_ack (); - virtual void process_term_req (zmq::own_t *object_); - virtual void process_term (int linger_); - virtual void process_term_ack (); - virtual void process_reap (zmq::socket_base_t *socket_); - virtual void process_reaped (); - - // Special handler called after a command that requires a seqnum - // was processed. The implementation should catch up with its counter - // of processed commands here. - virtual void process_seqnum (); - - private: - - // Context provides access to the global state. - zmq::ctx_t *ctx; - - // Thread ID of the thread the object belongs to. - uint32_t tid; - - void send_command (command_t &cmd_); - - object_t (const object_t&); - const object_t &operator = (const object_t&); - }; - -} - -#endif diff --git a/src/options.cpp b/src/options.cpp deleted file mode 100644 index ea932b0..0000000 --- a/src/options.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> - -#include "options.hpp" -#include "err.hpp" -#include "../include/zmq_utils.h" - -zmq::options_t::options_t () : - sndhwm (1000), - rcvhwm (1000), - affinity (0), - identity_size (0), - rate (100), - recovery_ivl (10000), - multicast_hops (1), - sndbuf (0), - rcvbuf (0), - type (-1), - linger (-1), - reconnect_ivl (100), - reconnect_ivl_max (0), - backlog (100), - maxmsgsize (-1), - rcvtimeo (-1), - sndtimeo (-1), - ipv6 (0), - immediate (0), - filter (false), - recv_identity (false), - raw_sock (false), - tcp_keepalive (-1), - tcp_keepalive_cnt (-1), - tcp_keepalive_idle (-1), - tcp_keepalive_intvl (-1), - mechanism (ZMQ_NULL), - as_server (0), - socket_id (0), - conflate (false) -{ -} - -int zmq::options_t::setsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - bool is_int = (optvallen_ == sizeof (int)); - int value = is_int? *((int *) optval_): 0; - - switch (option_) { - case ZMQ_SNDHWM: - if (is_int && value >= 0) { - sndhwm = value; - return 0; - } - break; - - case ZMQ_RCVHWM: - if (is_int && value >= 0) { - rcvhwm = value; - return 0; - } - break; - - case ZMQ_AFFINITY: - if (optvallen_ == sizeof (uint64_t)) { - affinity = *((uint64_t*) optval_); - return 0; - } - break; - - case ZMQ_IDENTITY: - // Empty identity is invalid as well as identity longer than - // 255 bytes. Identity starting with binary zero is invalid - // as these are used for auto-generated identities. - if (optvallen_ > 0 && optvallen_ < 256 - && *((const unsigned char *) optval_) != 0) { - identity_size = optvallen_; - memcpy (identity, optval_, identity_size); - return 0; - } - break; - - case ZMQ_RATE: - if (is_int && value > 0) { - rate = value; - return 0; - } - break; - - case ZMQ_RECOVERY_IVL: - if (is_int && value >= 0) { - recovery_ivl = value; - return 0; - } - break; - - case ZMQ_SNDBUF: - if (is_int && value >= 0) { - sndbuf = value; - return 0; - } - break; - - case ZMQ_RCVBUF: - if (is_int && value >= 0) { - rcvbuf = value; - return 0; - } - break; - - case ZMQ_LINGER: - if (is_int && value >= -1) { - linger = value; - return 0; - } - break; - - case ZMQ_RECONNECT_IVL: - if (is_int && value >= -1) { - reconnect_ivl = value; - return 0; - } - break; - - case ZMQ_RECONNECT_IVL_MAX: - if (is_int && value >= 0) { - reconnect_ivl_max = value; - return 0; - } - break; - - case ZMQ_BACKLOG: - if (is_int && value >= 0) { - backlog = value; - return 0; - } - break; - - case ZMQ_MAXMSGSIZE: - if (optvallen_ == sizeof (int64_t)) { - maxmsgsize = *((int64_t *) optval_); - return 0; - } - break; - - case ZMQ_MULTICAST_HOPS: - if (is_int && value > 0) { - multicast_hops = value; - return 0; - } - break; - - case ZMQ_RCVTIMEO: - if (is_int && value >= -1) { - rcvtimeo = value; - return 0; - } - break; - - case ZMQ_SNDTIMEO: - if (is_int && value >= -1) { - sndtimeo = value; - return 0; - } - break; - - /* Deprecated in favor of ZMQ_IPV6 */ - case ZMQ_IPV4ONLY: - if (is_int && (value == 0 || value == 1)) { - ipv6 = (value == 0); - return 0; - } - break; - - /* To replace the somewhat surprising IPV4ONLY */ - case ZMQ_IPV6: - if (is_int && (value == 0 || value == 1)) { - ipv6 = (value != 0); - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE: - if (is_int && (value >= -1 || value <= 1)) { - tcp_keepalive = value; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_CNT: - if (is_int && (value == -1 || value >= 0)) { - tcp_keepalive_cnt = value; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_IDLE: - if (is_int && (value == -1 || value >= 0)) { - tcp_keepalive_idle = value; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_INTVL: - if (is_int && (value == -1 || value >= 0)) { - tcp_keepalive_intvl = value; - return 0; - } - break; - - case ZMQ_IMMEDIATE: - if (is_int && (value == 0 || value == 1)) { - immediate = value; - return 0; - } - break; - - case ZMQ_TCP_ACCEPT_FILTER: - if (optvallen_ == 0 && optval_ == NULL) { - tcp_accept_filters.clear (); - return 0; - } - else - if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) { - std::string filter_str ((const char *) optval_, optvallen_); - tcp_address_mask_t mask; - int rc = mask.resolve (filter_str.c_str (), ipv6); - if (rc == 0) { - tcp_accept_filters.push_back (mask); - return 0; - } - } - break; - - case ZMQ_PLAIN_SERVER: - if (is_int && (value == 0 || value == 1)) { - as_server = value; - mechanism = value? ZMQ_PLAIN: ZMQ_NULL; - return 0; - } - break; - - case ZMQ_PLAIN_USERNAME: - if (optvallen_ == 0 && optval_ == NULL) { - mechanism = ZMQ_NULL; - return 0; - } - else - if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { - plain_username.assign ((const char *) optval_, optvallen_); - as_server = 0; - mechanism = ZMQ_PLAIN; - return 0; - } - break; - - case ZMQ_PLAIN_PASSWORD: - if (optvallen_ == 0 && optval_ == NULL) { - mechanism = ZMQ_NULL; - return 0; - } - else - if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { - plain_password.assign ((const char *) optval_, optvallen_); - as_server = 0; - mechanism = ZMQ_PLAIN; - return 0; - } - break; - - case ZMQ_ZAP_DOMAIN: - if (optvallen_ < 256) { - zap_domain.assign ((const char *) optval_, optvallen_); - return 0; - } - break; - - // If libsodium isn't installed, these options provoke EINVAL -# ifdef HAVE_LIBSODIUM - case ZMQ_CURVE_SERVER: - if (is_int && (value == 0 || value == 1)) { - as_server = value; - mechanism = value? ZMQ_CURVE: ZMQ_NULL; - return 0; - } - break; - - case ZMQ_CURVE_PUBLICKEY: - if (optvallen_ == CURVE_KEYSIZE) { - memcpy (curve_public_key, optval_, CURVE_KEYSIZE); - mechanism = ZMQ_CURVE; - return 0; - } - else - if (optvallen_ == CURVE_KEYSIZE_Z85) { - zmq_z85_decode (curve_public_key, (char *) optval_); - mechanism = ZMQ_CURVE; - return 0; - } - break; - - case ZMQ_CURVE_SECRETKEY: - if (optvallen_ == CURVE_KEYSIZE) { - memcpy (curve_secret_key, optval_, CURVE_KEYSIZE); - mechanism = ZMQ_CURVE; - return 0; - } - else - if (optvallen_ == CURVE_KEYSIZE_Z85) { - zmq_z85_decode (curve_secret_key, (char *) optval_); - mechanism = ZMQ_CURVE; - return 0; - } - break; - - case ZMQ_CURVE_SERVERKEY: - if (optvallen_ == CURVE_KEYSIZE) { - memcpy (curve_server_key, optval_, CURVE_KEYSIZE); - as_server = 0; - mechanism = ZMQ_CURVE; - return 0; - } - else - if (optvallen_ == CURVE_KEYSIZE_Z85) { - zmq_z85_decode (curve_server_key, (char *) optval_); - as_server = 0; - mechanism = ZMQ_CURVE; - return 0; - } - break; -# endif - - case ZMQ_CONFLATE: - if (is_int && (value == 0 || value == 1)) { - conflate = (value != 0); - return 0; - } - break; - - default: - break; - } - errno = EINVAL; - return -1; -} - -int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) -{ - bool is_int = (*optvallen_ == sizeof (int)); - int *value = (int *) optval_; - - switch (option_) { - case ZMQ_SNDHWM: - if (is_int) { - *value = sndhwm; - return 0; - } - break; - - case ZMQ_RCVHWM: - if (is_int) { - *value = rcvhwm; - return 0; - } - break; - - case ZMQ_AFFINITY: - if (*optvallen_ == sizeof (uint64_t)) { - *((uint64_t *) optval_) = affinity; - return 0; - } - break; - - case ZMQ_IDENTITY: - if (*optvallen_ >= identity_size) { - memcpy (optval_, identity, identity_size); - *optvallen_ = identity_size; - return 0; - } - break; - - case ZMQ_RATE: - if (is_int) { - *value = rate; - return 0; - } - break; - - case ZMQ_RECOVERY_IVL: - if (is_int) { - *value = recovery_ivl; - return 0; - } - break; - - case ZMQ_SNDBUF: - if (is_int) { - *value = sndbuf; - return 0; - } - break; - - case ZMQ_RCVBUF: - if (is_int) { - *value = rcvbuf; - return 0; - } - break; - - case ZMQ_TYPE: - if (is_int) { - *value = type; - return 0; - } - break; - - case ZMQ_LINGER: - if (is_int) { - *value = linger; - return 0; - } - break; - - case ZMQ_RECONNECT_IVL: - if (is_int) { - *value = reconnect_ivl; - return 0; - } - break; - - case ZMQ_RECONNECT_IVL_MAX: - if (is_int) { - *value = reconnect_ivl_max; - return 0; - } - break; - - case ZMQ_BACKLOG: - if (is_int) { - *value = backlog; - return 0; - } - break; - - case ZMQ_MAXMSGSIZE: - if (*optvallen_ == sizeof (int64_t)) { - *((int64_t *) optval_) = maxmsgsize; - *optvallen_ = sizeof (int64_t); - return 0; - } - break; - - case ZMQ_MULTICAST_HOPS: - if (is_int) { - *value = multicast_hops; - return 0; - } - break; - - case ZMQ_RCVTIMEO: - if (is_int) { - *value = rcvtimeo; - return 0; - } - break; - - case ZMQ_SNDTIMEO: - if (is_int) { - *value = sndtimeo; - return 0; - } - break; - - case ZMQ_IPV4ONLY: - if (is_int) { - *value = 1 - ipv6; - return 0; - } - break; - - case ZMQ_IPV6: - if (is_int) { - *value = ipv6; - return 0; - } - break; - - case ZMQ_IMMEDIATE: - if (is_int) { - *value = immediate; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE: - if (is_int) { - *value = tcp_keepalive; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_CNT: - if (is_int) { - *value = tcp_keepalive_cnt; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_IDLE: - if (is_int) { - *value = tcp_keepalive_idle; - return 0; - } - break; - - case ZMQ_TCP_KEEPALIVE_INTVL: - if (is_int) { - *value = tcp_keepalive_intvl; - return 0; - } - break; - - case ZMQ_MECHANISM: - if (is_int) { - *value = mechanism; - return 0; - } - break; - - case ZMQ_PLAIN_SERVER: - if (is_int) { - *value = as_server && mechanism == ZMQ_PLAIN; - return 0; - } - break; - - case ZMQ_PLAIN_USERNAME: - if (*optvallen_ >= plain_username.size () + 1) { - memcpy (optval_, plain_username.c_str (), plain_username.size () + 1); - *optvallen_ = plain_username.size () + 1; - return 0; - } - break; - - case ZMQ_PLAIN_PASSWORD: - if (*optvallen_ >= plain_password.size () + 1) { - memcpy (optval_, plain_password.c_str (), plain_password.size () + 1); - *optvallen_ = plain_password.size () + 1; - return 0; - } - break; - - case ZMQ_ZAP_DOMAIN: - if (*optvallen_ >= zap_domain.size () + 1) { - memcpy (optval_, zap_domain.c_str (), zap_domain.size () + 1); - *optvallen_ = zap_domain.size () + 1; - return 0; - } - break; - - // If libsodium isn't installed, these options provoke EINVAL -# ifdef HAVE_LIBSODIUM - case ZMQ_CURVE_SERVER: - if (is_int) { - *value = as_server && mechanism == ZMQ_CURVE; - return 0; - } - break; - - case ZMQ_CURVE_PUBLICKEY: - if (*optvallen_ == CURVE_KEYSIZE) { - memcpy (optval_, curve_public_key, CURVE_KEYSIZE); - return 0; - } - else - if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { - zmq_z85_encode ((char *) optval_, curve_public_key, CURVE_KEYSIZE); - return 0; - } - break; - - case ZMQ_CURVE_SECRETKEY: - if (*optvallen_ == CURVE_KEYSIZE) { - memcpy (optval_, curve_secret_key, CURVE_KEYSIZE); - return 0; - } - else - if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { - zmq_z85_encode ((char *) optval_, curve_secret_key, CURVE_KEYSIZE); - return 0; - } - break; - - case ZMQ_CURVE_SERVERKEY: - if (*optvallen_ == CURVE_KEYSIZE) { - memcpy (optval_, curve_server_key, CURVE_KEYSIZE); - return 0; - } - else - if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { - zmq_z85_encode ((char *) optval_, curve_server_key, CURVE_KEYSIZE); - return 0; - } - break; -# endif - - case ZMQ_CONFLATE: - if (is_int) { - *value = conflate; - return 0; - } - break; - - } - errno = EINVAL; - return -1; -} diff --git a/src/options.hpp b/src/options.hpp deleted file mode 100644 index 5154fab..0000000 --- a/src/options.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_OPTIONS_HPP_INCLUDED__ -#define __ZMQ_OPTIONS_HPP_INCLUDED__ - -#include <string> -#include <vector> - -#include "stddef.h" -#include "stdint.hpp" -#include "tcp_address.hpp" -#include "../include/zmq.h" - -// Normal base 256 key is 32 bytes -#define CURVE_KEYSIZE 32 -// Key encoded using Z85 is 40 bytes -#define CURVE_KEYSIZE_Z85 40 - -namespace zmq -{ - struct options_t - { - options_t (); - - int setsockopt (int option_, const void *optval_, size_t optvallen_); - int getsockopt (int option_, void *optval_, size_t *optvallen_); - - // High-water marks for message pipes. - int sndhwm; - int rcvhwm; - - // I/O thread affinity. - uint64_t affinity; - - // Socket identity - unsigned char identity_size; - unsigned char identity [256]; - - // Maximum transfer rate [kb/s]. Default 100kb/s. - int rate; - - // Reliability time interval [ms]. Default 10 seconds. - int recovery_ivl; - - // Sets the time-to-live field in every multicast packet sent. - int multicast_hops; - - // SO_SNDBUF and SO_RCVBUF to be passed to underlying transport sockets. - int sndbuf; - int rcvbuf; - - // Socket type. - int type; - - // Linger time, in milliseconds. - int linger; - - // Minimum interval between attempts to reconnect, in milliseconds. - // Default 100ms - int reconnect_ivl; - - // Maximum interval between attempts to reconnect, in milliseconds. - // Default 0 (unused) - int reconnect_ivl_max; - - // Maximum backlog for pending connections. - int backlog; - - // Maximal size of message to handle. - int64_t maxmsgsize; - - // The timeout for send/recv operations for this socket. - int rcvtimeo; - int sndtimeo; - - // If true, IPv6 is enabled (as well as IPv4) - bool ipv6; - - // If 1, connecting pipes are not attached immediately, meaning a send() - // on a socket with only connecting pipes would block - int immediate; - - // If 1, (X)SUB socket should filter the messages. If 0, it should not. - bool filter; - - // If true, the identity message is forwarded to the socket. - bool recv_identity; - - // if true, router socket accepts non-zmq tcp connections - bool raw_sock; - - // TCP keep-alive settings. - // Defaults to -1 = do not change socket options - int tcp_keepalive; - int tcp_keepalive_cnt; - int tcp_keepalive_idle; - int tcp_keepalive_intvl; - - // TCP accept() filters - typedef std::vector <tcp_address_mask_t> tcp_accept_filters_t; - tcp_accept_filters_t tcp_accept_filters; - - // Security mechanism for all connections on this socket - int mechanism; - - // If peer is acting as server for PLAIN or CURVE mechanisms - int as_server; - - // ZAP authentication domain - std::string zap_domain; - - // Security credentials for PLAIN mechanism - std::string plain_username; - std::string plain_password; - - // Security credentials for CURVE mechanism - uint8_t curve_public_key [CURVE_KEYSIZE]; - uint8_t curve_secret_key [CURVE_KEYSIZE]; - uint8_t curve_server_key [CURVE_KEYSIZE]; - - // ID of the socket. - int socket_id; - - // If true, socket conflates outgoing/incoming messages. - // Applicable to dealer, push/pull, pub/sub socket types. - // Cannot receive multi-part messages. - // Ignores hwm - bool conflate; - }; -} - -#endif diff --git a/src/own.cpp b/src/own.cpp deleted file mode 100644 index bbde1c5..0000000 --- a/src/own.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "own.hpp" -#include "err.hpp" -#include "io_thread.hpp" - -zmq::own_t::own_t (class ctx_t *parent_, uint32_t tid_) : - object_t (parent_, tid_), - terminating (false), - sent_seqnum (0), - processed_seqnum (0), - owner (NULL), - term_acks (0) -{ -} - -zmq::own_t::own_t (io_thread_t *io_thread_, const options_t &options_) : - object_t (io_thread_), - options (options_), - terminating (false), - sent_seqnum (0), - processed_seqnum (0), - owner (NULL), - term_acks (0) -{ -} - -zmq::own_t::~own_t () -{ -} - -void zmq::own_t::set_owner (own_t *owner_) -{ - zmq_assert (!owner); - owner = owner_; -} - -void zmq::own_t::inc_seqnum () -{ - // This function may be called from a different thread! - sent_seqnum.add (1); -} - -void zmq::own_t::process_seqnum () -{ - // Catch up with counter of processed commands. - processed_seqnum++; - - // We may have catched up and still have pending terms acks. - check_term_acks (); -} - -void zmq::own_t::launch_child (own_t *object_) -{ - // Specify the owner of the object. - object_->set_owner (this); - - // Plug the object into the I/O thread. - send_plug (object_); - - // Take ownership of the object. - send_own (this, object_); -} - -void zmq::own_t::term_child (own_t *object_) -{ - process_term_req (object_); -} - -void zmq::own_t::process_term_req (own_t *object_) -{ - // When shutting down we can ignore termination requests from owned - // objects. The termination request was already sent to the object. - if (terminating) - return; - - // If I/O object is well and alive let's ask it to terminate. - owned_t::iterator it = std::find (owned.begin (), owned.end (), object_); - - // If not found, we assume that termination request was already sent to - // the object so we can safely ignore the request. - if (it == owned.end ()) - return; - - owned.erase (it); - register_term_acks (1); - - // Note that this object is the root of the (partial shutdown) thus, its - // value of linger is used, rather than the value stored by the children. - send_term (object_, options.linger); -} - -void zmq::own_t::process_own (own_t *object_) -{ - // If the object is already being shut down, new owned objects are - // immediately asked to terminate. Note that linger is set to zero. - if (terminating) { - register_term_acks (1); - send_term (object_, 0); - return; - } - - // Store the reference to the owned object. - owned.insert (object_); -} - -void zmq::own_t::terminate () -{ - // If termination is already underway, there's no point - // in starting it anew. - if (terminating) - return; - - // As for the root of the ownership tree, there's noone to terminate it, - // so it has to terminate itself. - if (!owner) { - process_term (options.linger); - return; - } - - // If I am an owned object, I'll ask my owner to terminate me. - send_term_req (owner, this); -} - -bool zmq::own_t::is_terminating () -{ - return terminating; -} - -void zmq::own_t::process_term (int linger_) -{ - // Double termination should never happen. - zmq_assert (!terminating); - - // Send termination request to all owned objects. - for (owned_t::iterator it = owned.begin (); it != owned.end (); ++it) - send_term (*it, linger_); - register_term_acks ((int) owned.size ()); - owned.clear (); - - // Start termination process and check whether by chance we cannot - // terminate immediately. - terminating = true; - check_term_acks (); -} - -void zmq::own_t::register_term_acks (int count_) -{ - term_acks += count_; -} - -void zmq::own_t::unregister_term_ack () -{ - zmq_assert (term_acks > 0); - term_acks--; - - // This may be a last ack we are waiting for before termination... - check_term_acks (); -} - -void zmq::own_t::process_term_ack () -{ - unregister_term_ack (); -} - -void zmq::own_t::check_term_acks () -{ - if (terminating && processed_seqnum == sent_seqnum.get () && - term_acks == 0) { - - // Sanity check. There should be no active children at this point. - zmq_assert (owned.empty ()); - - // The root object has nobody to confirm the termination to. - // Other nodes will confirm the termination to the owner. - if (owner) - send_term_ack (owner); - - // Deallocate the resources. - process_destroy (); - } -} - -void zmq::own_t::process_destroy () -{ - delete this; -} - diff --git a/src/own.hpp b/src/own.hpp deleted file mode 100644 index f14c578..0000000 --- a/src/own.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_OWN_HPP_INCLUDED__ -#define __ZMQ_OWN_HPP_INCLUDED__ - -#include <set> -#include <algorithm> - -#include "object.hpp" -#include "options.hpp" -#include "atomic_counter.hpp" -#include "stdint.hpp" - -namespace zmq -{ - - class ctx_t; - class io_thread_t; - - // Base class for objects forming a part of ownership hierarchy. - // It handles initialisation and destruction of such objects. - - class own_t : public object_t - { - public: - - // Note that the owner is unspecified in the constructor. - // It'll be supplied later on when the object is plugged in. - - // The object is not living within an I/O thread. It has it's own - // thread outside of 0MQ infrastructure. - own_t (zmq::ctx_t *parent_, uint32_t tid_); - - // The object is living within I/O thread. - own_t (zmq::io_thread_t *io_thread_, const options_t &options_); - - // When another owned object wants to send command to this object - // it calls this function to let it know it should not shut down - // before the command is delivered. - void inc_seqnum (); - - // Use following two functions to wait for arbitrary events before - // terminating. Just add number of events to wait for using - // register_tem_acks functions. When event occurs, call - // remove_term_ack. When number of pending acks reaches zero - // object will be deallocated. - void register_term_acks (int count_); - void unregister_term_ack (); - - protected: - - // Launch the supplied object and become its owner. - void launch_child (own_t *object_); - - // Terminate owned object - void term_child (own_t *object_); - - // Ask owner object to terminate this object. It may take a while - // while actual termination is started. This function should not be - // called more than once. - void terminate (); - - // Returns true if the object is in process of termination. - bool is_terminating (); - - // Derived object destroys own_t. There's no point in allowing - // others to invoke the destructor. At the same time, it has to be - // virtual so that generic own_t deallocation mechanism destroys - // specific type of the owned object correctly. - virtual ~own_t (); - - // Term handler is protocted rather than private so that it can - // be intercepted by the derived class. This is useful to add custom - // steps to the beginning of the termination process. - void process_term (int linger_); - - // A place to hook in when phyicallal destruction of the object - // is to be delayed. - virtual void process_destroy (); - - // Socket options associated with this object. - options_t options; - - private: - - // Set owner of the object - void set_owner (own_t *owner_); - - // Handlers for incoming commands. - void process_own (own_t *object_); - void process_term_req (own_t *object_); - void process_term_ack (); - void process_seqnum (); - - // Check whether all the peding term acks were delivered. - // If so, deallocate this object. - void check_term_acks (); - - // True if termination was already initiated. If so, we can destroy - // the object if there are no more child objects or pending term acks. - bool terminating; - - // Sequence number of the last command sent to this object. - atomic_counter_t sent_seqnum; - - // Sequence number of the last command processed by this object. - uint64_t processed_seqnum; - - // Socket owning this object. It's responsible for shutting down - // this object. - own_t *owner; - - // List of all objects owned by this socket. We are responsible - // for deallocating them before we quit. - typedef std::set <own_t*> owned_t; - owned_t owned; - - // Number of events we have to get before we can destroy the object. - int term_acks; - - own_t (const own_t&); - const own_t &operator = (const own_t&); - }; - -} - -#endif diff --git a/src/pair.cpp b/src/pair.cpp deleted file mode 100644 index 66efab9..0000000 --- a/src/pair.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "pair.hpp" -#include "err.hpp" -#include "pipe.hpp" -#include "msg.hpp" - -zmq::pair_t::pair_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - pipe (NULL) -{ - options.type = ZMQ_PAIR; -} - -zmq::pair_t::~pair_t () -{ - zmq_assert (!pipe); -} - -void zmq::pair_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void)subscribe_to_all_; - - zmq_assert (pipe_ != NULL); - - // ZMQ_PAIR socket can only be connected to a single peer. - // The socket rejects any further connection requests. - if (pipe == NULL) - pipe = pipe_; - else - pipe_->terminate (false); -} - -void zmq::pair_t::xpipe_terminated (pipe_t *pipe_) -{ - if (pipe_ == pipe) - pipe = NULL; -} - -void zmq::pair_t::xread_activated (pipe_t *) -{ - // There's just one pipe. No lists of active and inactive pipes. - // There's nothing to do here. -} - -void zmq::pair_t::xwrite_activated (pipe_t *) -{ - // There's just one pipe. No lists of active and inactive pipes. - // There's nothing to do here. -} - -int zmq::pair_t::xsend (msg_t *msg_) -{ - if (!pipe || !pipe->write (msg_)) { - errno = EAGAIN; - return -1; - } - - if (!(msg_->flags () & msg_t::more)) - pipe->flush (); - - // Detach the original message from the data buffer. - int rc = msg_->init (); - errno_assert (rc == 0); - - return 0; -} - -int zmq::pair_t::xrecv (msg_t *msg_) -{ - // Deallocate old content of the message. - int rc = msg_->close (); - errno_assert (rc == 0); - - if (!pipe || !pipe->read (msg_)) { - - // Initialise the output parameter to be a 0-byte message. - rc = msg_->init (); - errno_assert (rc == 0); - - errno = EAGAIN; - return -1; - } - return 0; -} - -bool zmq::pair_t::xhas_in () -{ - if (!pipe) - return false; - - return pipe->check_read (); -} - -bool zmq::pair_t::xhas_out () -{ - if (!pipe) - return false; - - return pipe->check_write (); -} diff --git a/src/pair.hpp b/src/pair.hpp deleted file mode 100644 index 754c8ad..0000000 --- a/src/pair.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PAIR_HPP_INCLUDED__ -#define __ZMQ_PAIR_HPP_INCLUDED__ - -#include "socket_base.hpp" -#include "session_base.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class pipe_t; - class io_thread_t; - - class pair_t : - public socket_base_t - { - public: - - pair_t (zmq::ctx_t *parent_, uint32_t tid_, int sid); - ~pair_t (); - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - - zmq::pipe_t *pipe; - - pair_t (const pair_t&); - const pair_t &operator = (const pair_t&); - }; - -} - -#endif diff --git a/src/pgm_receiver.cpp b/src/pgm_receiver.cpp deleted file mode 100644 index 4068969..0000000 --- a/src/pgm_receiver.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_OPENPGM - -#include <new> - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "pgm_receiver.hpp" -#include "session_base.hpp" -#include "v1_decoder.hpp" -#include "stdint.hpp" -#include "wire.hpp" -#include "err.hpp" - -zmq::pgm_receiver_t::pgm_receiver_t (class io_thread_t *parent_, - const options_t &options_) : - io_object_t (parent_), - has_rx_timer (false), - pgm_socket (true, options_), - options (options_), - session (NULL), - active_tsi (NULL), - insize (0) -{ -} - -zmq::pgm_receiver_t::~pgm_receiver_t () -{ - // Destructor should not be called before unplug. - zmq_assert (peers.empty ()); -} - -int zmq::pgm_receiver_t::init (bool udp_encapsulation_, const char *network_) -{ - return pgm_socket.init (udp_encapsulation_, network_); -} - -void zmq::pgm_receiver_t::plug (io_thread_t *io_thread_, - session_base_t *session_) -{ - // Retrieve PGM fds and start polling. - fd_t socket_fd = retired_fd; - fd_t waiting_pipe_fd = retired_fd; - pgm_socket.get_receiver_fds (&socket_fd, &waiting_pipe_fd); - socket_handle = add_fd (socket_fd); - pipe_handle = add_fd (waiting_pipe_fd); - set_pollin (pipe_handle); - set_pollin (socket_handle); - - session = session_; - - // If there are any subscriptions already queued in the session, drop them. - drop_subscriptions (); -} - -void zmq::pgm_receiver_t::unplug () -{ - // Delete decoders. - for (peers_t::iterator it = peers.begin (); it != peers.end (); ++it) { - if (it->second.decoder != NULL) - delete it->second.decoder; - } - peers.clear (); - active_tsi = NULL; - - if (has_rx_timer) { - cancel_timer (rx_timer_id); - has_rx_timer = false; - } - - rm_fd (socket_handle); - rm_fd (pipe_handle); - - session = NULL; -} - -void zmq::pgm_receiver_t::terminate () -{ - unplug (); - delete this; -} - -void zmq::pgm_receiver_t::restart_output () -{ - drop_subscriptions (); -} - -void zmq::pgm_receiver_t::restart_input () -{ - zmq_assert (session != NULL); - zmq_assert (active_tsi != NULL); - - const peers_t::iterator it = peers.find (*active_tsi); - zmq_assert (it != peers.end ()); - zmq_assert (it->second.joined); - - // Push the pending message into the session. - int rc = session->push_msg (it->second.decoder->msg ()); - errno_assert (rc == 0); - - if (insize > 0) { - rc = process_input (it->second.decoder); - if (rc == -1) { - // HWM reached; we will try later. - if (errno == EAGAIN) { - session->flush (); - return; - } - // Data error. Delete message decoder, mark the - // peer as not joined and drop remaining data. - it->second.joined = false; - delete it->second.decoder; - it->second.decoder = NULL; - insize = 0; - } - } - - // Resume polling. - set_pollin (pipe_handle); - set_pollin (socket_handle); - - active_tsi = NULL; - in_event (); -} - -void zmq::pgm_receiver_t::in_event () -{ - // Read data from the underlying pgm_socket. - const pgm_tsi_t *tsi = NULL; - - if (has_rx_timer) { - cancel_timer (rx_timer_id); - has_rx_timer = false; - } - - // TODO: This loop can effectively block other engines in the same I/O - // thread in the case of high load. - while (true) { - - // Get new batch of data. - // Note the workaround made not to break strict-aliasing rules. - void *tmp = NULL; - ssize_t received = pgm_socket.receive (&tmp, &tsi); - inpos = (unsigned char*) tmp; - - // No data to process. This may happen if the packet received is - // neither ODATA nor ODATA. - if (received == 0) { - if (errno == ENOMEM || errno == EBUSY) { - const long timeout = pgm_socket.get_rx_timeout (); - add_timer (timeout, rx_timer_id); - has_rx_timer = true; - } - break; - } - - // Find the peer based on its TSI. - peers_t::iterator it = peers.find (*tsi); - - // Data loss. Delete decoder and mark the peer as disjoint. - if (received == -1) { - if (it != peers.end ()) { - it->second.joined = false; - if (it->second.decoder != NULL) { - delete it->second.decoder; - it->second.decoder = NULL; - } - } - break; - } - - // New peer. Add it to the list of know but unjoint peers. - if (it == peers.end ()) { - peer_info_t peer_info = {false, NULL}; - it = peers.insert (peers_t::value_type (*tsi, peer_info)).first; - } - - insize = static_cast <size_t> (received); - - // Read the offset of the fist message in the current packet. - zmq_assert (insize >= sizeof (uint16_t)); - uint16_t offset = get_uint16 (inpos); - inpos += sizeof (uint16_t); - insize -= sizeof (uint16_t); - - // Join the stream if needed. - if (!it->second.joined) { - - // There is no beginning of the message in current packet. - // Ignore the data. - if (offset == 0xffff) - continue; - - zmq_assert (offset <= insize); - zmq_assert (it->second.decoder == NULL); - - // We have to move data to the begining of the first message. - inpos += offset; - insize -= offset; - - // Mark the stream as joined. - it->second.joined = true; - - // Create and connect decoder for the peer. - it->second.decoder = new (std::nothrow) - v1_decoder_t (0, options.maxmsgsize); - alloc_assert (it->second.decoder); - } - - int rc = process_input (it->second.decoder); - if (rc == -1) { - if (errno == EAGAIN) { - active_tsi = tsi; - - // Stop polling. - reset_pollin (pipe_handle); - reset_pollin (socket_handle); - - break; - } - - it->second.joined = false; - delete it->second.decoder; - it->second.decoder = NULL; - insize = 0; - } - } - - // Flush any messages decoder may have produced. - session->flush (); -} - -int zmq::pgm_receiver_t::process_input (v1_decoder_t *decoder) -{ - zmq_assert (session != NULL); - - while (insize > 0) { - size_t n = 0; - int rc = decoder->decode (inpos, insize, n); - if (rc == -1) - return -1; - inpos += n; - insize -= n; - if (rc == 0) - break; - rc = session->push_msg (decoder->msg ()); - if (rc == -1) { - errno_assert (errno == EAGAIN); - return -1; - } - } - return 0; -} - - -void zmq::pgm_receiver_t::timer_event (int token) -{ - zmq_assert (token == rx_timer_id); - - // Timer cancels on return by poller_base. - has_rx_timer = false; - in_event (); -} - -void zmq::pgm_receiver_t::drop_subscriptions () -{ - msg_t msg; - msg.init (); - while (session->pull_msg (&msg)) - msg.close (); -} - -#endif - diff --git a/src/pgm_receiver.hpp b/src/pgm_receiver.hpp deleted file mode 100644 index 1f5d2d4..0000000 --- a/src/pgm_receiver.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PGM_RECEIVER_HPP_INCLUDED__ -#define __ZMQ_PGM_RECEIVER_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_OPENPGM - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include <map> -#include <algorithm> - -#include "io_object.hpp" -#include "i_engine.hpp" -#include "options.hpp" -#include "v1_decoder.hpp" -#include "pgm_socket.hpp" - -namespace zmq -{ - - class io_thread_t; - class session_base_t; - - class pgm_receiver_t : public io_object_t, public i_engine - { - - public: - - pgm_receiver_t (zmq::io_thread_t *parent_, const options_t &options_); - ~pgm_receiver_t (); - - int init (bool udp_encapsulation_, const char *network_); - - // i_engine interface implementation. - void plug (zmq::io_thread_t *io_thread_, - zmq::session_base_t *session_); - void terminate (); - void restart_input (); - void restart_output (); - void zap_msg_available () {} - - // i_poll_events interface implementation. - void in_event (); - void timer_event (int token); - - private: - - // Unplug the engine from the session. - void unplug (); - - // Decode received data (inpos, insize) and forward decoded - // messages to the session. - int process_input (v1_decoder_t *decoder); - - // PGM is not able to move subscriptions upstream. Thus, drop all - // the pending subscriptions. - void drop_subscriptions (); - - // RX timeout timer ID. - enum {rx_timer_id = 0xa1}; - - // RX timer is running. - bool has_rx_timer; - - // If joined is true we are already getting messages from the peer. - // It it's false, we are getting data but still we haven't seen - // beginning of a message. - struct peer_info_t - { - bool joined; - v1_decoder_t *decoder; - }; - - struct tsi_comp - { - bool operator () (const pgm_tsi_t <si, - const pgm_tsi_t &rtsi) const - { - uint32_t ll[2], rl[2]; - memcpy (ll, <si, sizeof (ll)); - memcpy (rl, &rtsi, sizeof (rl)); - return (ll[0] < rl[0]) || (ll[0] == rl[0] && ll[1] < rl[1]); - } - }; - - typedef std::map <pgm_tsi_t, peer_info_t, tsi_comp> peers_t; - peers_t peers; - - // PGM socket. - pgm_socket_t pgm_socket; - - // Socket options. - options_t options; - - // Associated session. - zmq::session_base_t *session; - - const pgm_tsi_t *active_tsi; - - // Number of bytes not consumed by the decoder due to pipe overflow. - size_t insize; - - // Pointer to data still waiting to be processed by the decoder. - const unsigned char *inpos; - - // Poll handle associated with PGM socket. - handle_t socket_handle; - - // Poll handle associated with engine PGM waiting pipe. - handle_t pipe_handle; - - pgm_receiver_t (const pgm_receiver_t&); - const pgm_receiver_t &operator = (const pgm_receiver_t&); - }; - -} - -#endif - -#endif diff --git a/src/pgm_sender.cpp b/src/pgm_sender.cpp deleted file mode 100644 index 0be7c6d..0000000 --- a/src/pgm_sender.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_OPENPGM - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include <stdlib.h> - -#include "io_thread.hpp" -#include "pgm_sender.hpp" -#include "session_base.hpp" -#include "err.hpp" -#include "wire.hpp" -#include "stdint.hpp" - -zmq::pgm_sender_t::pgm_sender_t (io_thread_t *parent_, - const options_t &options_) : - io_object_t (parent_), - has_tx_timer (false), - has_rx_timer (false), - session (NULL), - encoder (0), - more_flag (false), - pgm_socket (false, options_), - options (options_), - out_buffer (NULL), - out_buffer_size (0), - write_size (0) -{ - int rc = msg.init (); - errno_assert (rc == 0); -} - -int zmq::pgm_sender_t::init (bool udp_encapsulation_, const char *network_) -{ - int rc = pgm_socket.init (udp_encapsulation_, network_); - if (rc != 0) - return rc; - - out_buffer_size = pgm_socket.get_max_tsdu_size (); - out_buffer = (unsigned char*) malloc (out_buffer_size); - alloc_assert (out_buffer); - - return rc; -} - -void zmq::pgm_sender_t::plug (io_thread_t *io_thread_, session_base_t *session_) -{ - // Alocate 2 fds for PGM socket. - fd_t downlink_socket_fd = retired_fd; - fd_t uplink_socket_fd = retired_fd; - fd_t rdata_notify_fd = retired_fd; - fd_t pending_notify_fd = retired_fd; - - session = session_; - - // Fill fds from PGM transport and add them to the poller. - pgm_socket.get_sender_fds (&downlink_socket_fd, &uplink_socket_fd, - &rdata_notify_fd, &pending_notify_fd); - - handle = add_fd (downlink_socket_fd); - uplink_handle = add_fd (uplink_socket_fd); - rdata_notify_handle = add_fd (rdata_notify_fd); - pending_notify_handle = add_fd (pending_notify_fd); - - // Set POLLIN. We wont never want to stop polling for uplink = we never - // want to stop porocess NAKs. - set_pollin (uplink_handle); - set_pollin (rdata_notify_handle); - set_pollin (pending_notify_handle); - - // Set POLLOUT for downlink_socket_handle. - set_pollout (handle); -} - -void zmq::pgm_sender_t::unplug () -{ - if (has_rx_timer) { - cancel_timer (rx_timer_id); - has_rx_timer = false; - } - - if (has_tx_timer) { - cancel_timer (tx_timer_id); - has_tx_timer = false; - } - - rm_fd (handle); - rm_fd (uplink_handle); - rm_fd (rdata_notify_handle); - rm_fd (pending_notify_handle); - session = NULL; -} - -void zmq::pgm_sender_t::terminate () -{ - unplug (); - delete this; -} - -void zmq::pgm_sender_t::restart_output () -{ - set_pollout (handle); - out_event (); -} - -void zmq::pgm_sender_t::restart_input () -{ - zmq_assert (false); -} - -zmq::pgm_sender_t::~pgm_sender_t () -{ - int rc = msg.close (); - errno_assert (rc == 0); - - if (out_buffer) { - free (out_buffer); - out_buffer = NULL; - } -} - -void zmq::pgm_sender_t::in_event () -{ - if (has_rx_timer) { - cancel_timer (rx_timer_id); - has_rx_timer = false; - } - - // In-event on sender side means NAK or SPMR receiving from some peer. - pgm_socket.process_upstream (); - if (errno == ENOMEM || errno == EBUSY) { - const long timeout = pgm_socket.get_rx_timeout (); - add_timer (timeout, rx_timer_id); - has_rx_timer = true; - } -} - -void zmq::pgm_sender_t::out_event () -{ - // POLLOUT event from send socket. If write buffer is empty, - // try to read new data from the encoder. - if (write_size == 0) { - - // First two bytes (sizeof uint16_t) are used to store message - // offset in following steps. Note that by passing our buffer to - // the get data function we prevent it from returning its own buffer. - unsigned char *bf = out_buffer + sizeof (uint16_t); - size_t bfsz = out_buffer_size - sizeof (uint16_t); - uint16_t offset = 0xffff; - - size_t bytes = encoder.encode (&bf, bfsz); - while (bytes < bfsz) { - if (!more_flag && offset == 0xffff) - offset = static_cast <uint16_t> (bytes); - int rc = session->pull_msg (&msg); - if (rc == -1) - break; - more_flag = msg.flags () & msg_t::more; - encoder.load_msg (&msg); - bf = out_buffer + sizeof (uint16_t) + bytes; - bytes += encoder.encode (&bf, bfsz - bytes); - } - - // If there are no data to write stop polling for output. - if (bytes == 0) { - reset_pollout (handle); - return; - } - - write_size = sizeof (uint16_t) + bytes; - - // Put offset information in the buffer. - put_uint16 (out_buffer, offset); - } - - if (has_tx_timer) { - cancel_timer (tx_timer_id); - has_tx_timer = false; - } - - // Send the data. - size_t nbytes = pgm_socket.send (out_buffer, write_size); - - // We can write either all data or 0 which means rate limit reached. - if (nbytes == write_size) - write_size = 0; - else { - zmq_assert (nbytes == 0); - - if (errno == ENOMEM) { - const long timeout = pgm_socket.get_tx_timeout (); - add_timer (timeout, tx_timer_id); - has_tx_timer = true; - } - else - errno_assert (errno == EBUSY); - } -} - -void zmq::pgm_sender_t::timer_event (int token) -{ - // Timer cancels on return by poller_base. - if (token == rx_timer_id) { - has_rx_timer = false; - in_event (); - } - else - if (token == tx_timer_id) { - has_tx_timer = false; - out_event (); - } - else - zmq_assert (false); -} - -#endif - diff --git a/src/pgm_sender.hpp b/src/pgm_sender.hpp deleted file mode 100644 index 045cd47..0000000 --- a/src/pgm_sender.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PGM_SENDER_HPP_INCLUDED__ -#define __ZMQ_PGM_SENDER_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_OPENPGM - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "stdint.hpp" -#include "io_object.hpp" -#include "i_engine.hpp" -#include "options.hpp" -#include "pgm_socket.hpp" -#include "v1_encoder.hpp" -#include "msg.hpp" - -namespace zmq -{ - - class io_thread_t; - class session_base_t; - - class pgm_sender_t : public io_object_t, public i_engine - { - - public: - - pgm_sender_t (zmq::io_thread_t *parent_, const options_t &options_); - ~pgm_sender_t (); - - int init (bool udp_encapsulation_, const char *network_); - - // i_engine interface implementation. - void plug (zmq::io_thread_t *io_thread_, - zmq::session_base_t *session_); - void terminate (); - void restart_input (); - void restart_output (); - void zap_msg_available () {} - - // i_poll_events interface implementation. - void in_event (); - void out_event (); - void timer_event (int token); - - private: - - // Unplug the engine from the session. - void unplug (); - - // TX and RX timeout timer ID's. - enum {tx_timer_id = 0xa0, rx_timer_id = 0xa1}; - - // Timers are running. - bool has_tx_timer; - bool has_rx_timer; - - session_base_t *session; - - // Message encoder. - v1_encoder_t encoder; - - msg_t msg; - - // Keeps track of message boundaries. - bool more_flag; - - // PGM socket. - pgm_socket_t pgm_socket; - - // Socket options. - options_t options; - - // Poll handle associated with PGM socket. - handle_t handle; - handle_t uplink_handle; - handle_t rdata_notify_handle; - handle_t pending_notify_handle; - - // Output buffer from pgm_socket. - unsigned char *out_buffer; - - // Output buffer size. - size_t out_buffer_size; - - // Number of bytes in the buffer to be written to the socket. - // If zero, there are no data to be sent. - size_t write_size; - - pgm_sender_t (const pgm_sender_t&); - const pgm_sender_t &operator = (const pgm_sender_t&); - }; - -} -#endif - -#endif diff --git a/src/pgm_socket.cpp b/src/pgm_socket.cpp deleted file mode 100644 index 7925c6e..0000000 --- a/src/pgm_socket.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#ifdef ZMQ_HAVE_OPENPGM - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#ifdef ZMQ_HAVE_LINUX -#include <poll.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <string> - -#include "options.hpp" -#include "pgm_socket.hpp" -#include "config.hpp" -#include "err.hpp" -#include "random.hpp" -#include "stdint.hpp" - -#ifndef MSG_ERRQUEUE -#define MSG_ERRQUEUE 0x2000 -#endif - -zmq::pgm_socket_t::pgm_socket_t (bool receiver_, const options_t &options_) : - sock (NULL), - options (options_), - receiver (receiver_), - pgm_msgv (NULL), - pgm_msgv_len (0), - nbytes_rec (0), - nbytes_processed (0), - pgm_msgv_processed (0) -{ -} - -// Resolve PGM socket address. -// network_ of the form <interface & multicast group decls>:<IP port> -// e.g. eth0;239.192.0.1:7500 -// link-local;224.250.0.1,224.250.0.2;224.250.0.3:8000 -// ;[fe80::1%en0]:7500 -int zmq::pgm_socket_t::init_address (const char *network_, - struct pgm_addrinfo_t **res, uint16_t *port_number) -{ - // Parse port number, start from end for IPv6 - const char *port_delim = strrchr (network_, ':'); - if (!port_delim) { - errno = EINVAL; - return -1; - } - - *port_number = atoi (port_delim + 1); - - char network [256]; - if (port_delim - network_ >= (int) sizeof (network) - 1) { - errno = EINVAL; - return -1; - } - memset (network, '\0', sizeof (network)); - memcpy (network, network_, port_delim - network_); - - pgm_error_t *pgm_error = NULL; - struct pgm_addrinfo_t hints; - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = AF_UNSPEC; - if (!pgm_getaddrinfo (network, NULL, res, &pgm_error)) { - - // Invalid parameters don't set pgm_error_t. - zmq_assert (pgm_error != NULL); - if (pgm_error->domain == PGM_ERROR_DOMAIN_IF && - - // NB: cannot catch EAI_BADFLAGS. - ( pgm_error->code != PGM_ERROR_SERVICE && - pgm_error->code != PGM_ERROR_SOCKTNOSUPPORT)) { - - // User, host, or network configuration or transient error. - pgm_error_free (pgm_error); - errno = EINVAL; - return -1; - } - - // Fatal OpenPGM internal error. - zmq_assert (false); - } - return 0; -} - -// Create, bind and connect PGM socket. -int zmq::pgm_socket_t::init (bool udp_encapsulation_, const char *network_) -{ - // Can not open transport before destroying old one. - zmq_assert (sock == NULL); - zmq_assert (options.rate > 0); - - // Zero counter used in msgrecv. - nbytes_rec = 0; - nbytes_processed = 0; - pgm_msgv_processed = 0; - - uint16_t port_number; - struct pgm_addrinfo_t *res = NULL; - sa_family_t sa_family; - - pgm_error_t *pgm_error = NULL; - - if (init_address(network_, &res, &port_number) < 0) { - goto err_abort; - } - - zmq_assert (res != NULL); - - // Pick up detected IP family. - sa_family = res->ai_send_addrs[0].gsr_group.ss_family; - - // Create IP/PGM or UDP/PGM socket. - if (udp_encapsulation_) { - if (!pgm_socket (&sock, sa_family, SOCK_SEQPACKET, IPPROTO_UDP, - &pgm_error)) { - - // Invalid parameters don't set pgm_error_t. - zmq_assert (pgm_error != NULL); - if (pgm_error->domain == PGM_ERROR_DOMAIN_SOCKET && ( - pgm_error->code != PGM_ERROR_BADF && - pgm_error->code != PGM_ERROR_FAULT && - pgm_error->code != PGM_ERROR_NOPROTOOPT && - pgm_error->code != PGM_ERROR_FAILED)) - - // User, host, or network configuration or transient error. - goto err_abort; - - // Fatal OpenPGM internal error. - zmq_assert (false); - } - - // All options are of data type int - const int encapsulation_port = port_number; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_UDP_ENCAP_UCAST_PORT, - &encapsulation_port, sizeof (encapsulation_port))) - goto err_abort; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_UDP_ENCAP_MCAST_PORT, - &encapsulation_port, sizeof (encapsulation_port))) - goto err_abort; - } - else { - if (!pgm_socket (&sock, sa_family, SOCK_SEQPACKET, IPPROTO_PGM, - &pgm_error)) { - - // Invalid parameters don't set pgm_error_t. - zmq_assert (pgm_error != NULL); - if (pgm_error->domain == PGM_ERROR_DOMAIN_SOCKET && ( - pgm_error->code != PGM_ERROR_BADF && - pgm_error->code != PGM_ERROR_FAULT && - pgm_error->code != PGM_ERROR_NOPROTOOPT && - pgm_error->code != PGM_ERROR_FAILED)) - - // User, host, or network configuration or transient error. - goto err_abort; - - // Fatal OpenPGM internal error. - zmq_assert (false); - } - } - - { - const int rcvbuf = (int) options.rcvbuf; - if (rcvbuf) { - if (!pgm_setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &rcvbuf, - sizeof (rcvbuf))) - goto err_abort; - } - - const int sndbuf = (int) options.sndbuf; - if (sndbuf) { - if (!pgm_setsockopt (sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, - sizeof (sndbuf))) - goto err_abort; - } - - const int max_tpdu = (int) pgm_max_tpdu; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_MTU, &max_tpdu, - sizeof (max_tpdu))) - goto err_abort; - } - - if (receiver) { - const int recv_only = 1, - rxw_max_tpdu = (int) pgm_max_tpdu, - rxw_sqns = compute_sqns (rxw_max_tpdu), - peer_expiry = pgm_secs (300), - spmr_expiry = pgm_msecs (25), - nak_bo_ivl = pgm_msecs (50), - nak_rpt_ivl = pgm_msecs (200), - nak_rdata_ivl = pgm_msecs (200), - nak_data_retries = 50, - nak_ncf_retries = 50; - - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_RECV_ONLY, &recv_only, - sizeof (recv_only)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_RXW_SQNS, &rxw_sqns, - sizeof (rxw_sqns)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_PEER_EXPIRY, &peer_expiry, - sizeof (peer_expiry)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_SPMR_EXPIRY, &spmr_expiry, - sizeof (spmr_expiry)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_NAK_BO_IVL, &nak_bo_ivl, - sizeof (nak_bo_ivl)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_NAK_RPT_IVL, &nak_rpt_ivl, - sizeof (nak_rpt_ivl)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_NAK_RDATA_IVL, - &nak_rdata_ivl, sizeof (nak_rdata_ivl)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_NAK_DATA_RETRIES, - &nak_data_retries, sizeof (nak_data_retries)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_NAK_NCF_RETRIES, - &nak_ncf_retries, sizeof (nak_ncf_retries))) - goto err_abort; - } - else { - const int send_only = 1, - max_rte = (int) ((options.rate * 1000) / 8), - txw_max_tpdu = (int) pgm_max_tpdu, - txw_sqns = compute_sqns (txw_max_tpdu), - ambient_spm = pgm_secs (30), - heartbeat_spm[] = { pgm_msecs (100), - pgm_msecs (100), - pgm_msecs (100), - pgm_msecs (100), - pgm_msecs (1300), - pgm_secs (7), - pgm_secs (16), - pgm_secs (25), - pgm_secs (30) }; - - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_SEND_ONLY, - &send_only, sizeof (send_only)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_ODATA_MAX_RTE, - &max_rte, sizeof (max_rte)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_TXW_SQNS, - &txw_sqns, sizeof (txw_sqns)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_AMBIENT_SPM, - &ambient_spm, sizeof (ambient_spm)) || - !pgm_setsockopt (sock, IPPROTO_PGM, PGM_HEARTBEAT_SPM, - &heartbeat_spm, sizeof (heartbeat_spm))) - goto err_abort; - } - - // PGM transport GSI. - struct pgm_sockaddr_t addr; - - memset (&addr, 0, sizeof(addr)); - addr.sa_port = port_number; - addr.sa_addr.sport = DEFAULT_DATA_SOURCE_PORT; - - // Create random GSI. - uint32_t buf [2]; - buf [0] = generate_random (); - buf [1] = generate_random (); - if (!pgm_gsi_create_from_data (&addr.sa_addr.gsi, (uint8_t*) buf, 8)) - goto err_abort; - - - // Bind a transport to the specified network devices. - struct pgm_interface_req_t if_req; - memset (&if_req, 0, sizeof(if_req)); - if_req.ir_interface = res->ai_recv_addrs[0].gsr_interface; - if_req.ir_scope_id = 0; - if (AF_INET6 == sa_family) { - struct sockaddr_in6 sa6; - memcpy (&sa6, &res->ai_recv_addrs[0].gsr_group, sizeof (sa6)); - if_req.ir_scope_id = sa6.sin6_scope_id; - } - if (!pgm_bind3 (sock, &addr, sizeof (addr), &if_req, sizeof (if_req), - &if_req, sizeof (if_req), &pgm_error)) { - - // Invalid parameters don't set pgm_error_t. - zmq_assert (pgm_error != NULL); - if ((pgm_error->domain == PGM_ERROR_DOMAIN_SOCKET || - pgm_error->domain == PGM_ERROR_DOMAIN_IF) && ( - pgm_error->code != PGM_ERROR_INVAL && - pgm_error->code != PGM_ERROR_BADF && - pgm_error->code != PGM_ERROR_FAULT)) - - // User, host, or network configuration or transient error. - goto err_abort; - - // Fatal OpenPGM internal error. - zmq_assert (false); - } - - // Join IP multicast groups. - for (unsigned i = 0; i < res->ai_recv_addrs_len; i++) { - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_JOIN_GROUP, - &res->ai_recv_addrs [i], sizeof (struct group_req))) - goto err_abort; - } - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_SEND_GROUP, - &res->ai_send_addrs [0], sizeof (struct group_req))) - goto err_abort; - - pgm_freeaddrinfo (res); - res = NULL; - - // Set IP level parameters. - { - // Multicast loopback disabled by default - const int multicast_loop = 0; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_MULTICAST_LOOP, - &multicast_loop, sizeof (multicast_loop))) - goto err_abort; - - const int multicast_hops = options.multicast_hops; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_MULTICAST_HOPS, - &multicast_hops, sizeof (multicast_hops))) - goto err_abort; - - // Expedited Forwarding PHB for network elements, no ECN. - // Ignore return value due to varied runtime support. - const int dscp = 0x2e << 2; - if (AF_INET6 != sa_family) - pgm_setsockopt (sock, IPPROTO_PGM, PGM_TOS, - &dscp, sizeof (dscp)); - - const int nonblocking = 1; - if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_NOBLOCK, - &nonblocking, sizeof (nonblocking))) - goto err_abort; - } - - // Connect PGM transport to start state machine. - if (!pgm_connect (sock, &pgm_error)) { - - // Invalid parameters don't set pgm_error_t. - zmq_assert (pgm_error != NULL); - goto err_abort; - } - - // For receiver transport preallocate pgm_msgv array. - if (receiver) { - zmq_assert (in_batch_size > 0); - size_t max_tsdu_size = get_max_tsdu_size (); - pgm_msgv_len = (int) in_batch_size / max_tsdu_size; - if ((int) in_batch_size % max_tsdu_size) - pgm_msgv_len++; - zmq_assert (pgm_msgv_len); - - pgm_msgv = (pgm_msgv_t*) malloc (sizeof (pgm_msgv_t) * pgm_msgv_len); - alloc_assert (pgm_msgv); - } - - return 0; - -err_abort: - if (sock != NULL) { - pgm_close (sock, FALSE); - sock = NULL; - } - if (res != NULL) { - pgm_freeaddrinfo (res); - res = NULL; - } - if (pgm_error != NULL) { - pgm_error_free (pgm_error); - pgm_error = NULL; - } - errno = EINVAL; - return -1; -} - -zmq::pgm_socket_t::~pgm_socket_t () -{ - if (pgm_msgv) - free (pgm_msgv); - if (sock) - pgm_close (sock, TRUE); -} - -// Get receiver fds. receive_fd_ is signaled for incoming packets, -// waiting_pipe_fd_ is signaled for state driven events and data. -void zmq::pgm_socket_t::get_receiver_fds (fd_t *receive_fd_, - fd_t *waiting_pipe_fd_) -{ - socklen_t socklen; - bool rc; - - zmq_assert (receive_fd_); - zmq_assert (waiting_pipe_fd_); - - socklen = sizeof (*receive_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_RECV_SOCK, receive_fd_, - &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*receive_fd_)); - - socklen = sizeof (*waiting_pipe_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_PENDING_SOCK, waiting_pipe_fd_, - &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*waiting_pipe_fd_)); -} - -// Get fds and store them into user allocated memory. -// send_fd is for non-blocking send wire notifications. -// receive_fd_ is for incoming back-channel protocol packets. -// rdata_notify_fd_ is raised for waiting repair transmissions. -// pending_notify_fd_ is for state driven events. -void zmq::pgm_socket_t::get_sender_fds (fd_t *send_fd_, fd_t *receive_fd_, - fd_t *rdata_notify_fd_, fd_t *pending_notify_fd_) -{ - socklen_t socklen; - bool rc; - - zmq_assert (send_fd_); - zmq_assert (receive_fd_); - zmq_assert (rdata_notify_fd_); - zmq_assert (pending_notify_fd_); - - socklen = sizeof (*send_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_SEND_SOCK, send_fd_, &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*receive_fd_)); - - socklen = sizeof (*receive_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_RECV_SOCK, receive_fd_, - &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*receive_fd_)); - - socklen = sizeof (*rdata_notify_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_REPAIR_SOCK, rdata_notify_fd_, - &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*rdata_notify_fd_)); - - socklen = sizeof (*pending_notify_fd_); - rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_PENDING_SOCK, - pending_notify_fd_, &socklen); - zmq_assert (rc); - zmq_assert (socklen == sizeof (*pending_notify_fd_)); -} - -// Send one APDU, transmit window owned memory. -// data_len_ must be less than one TPDU. -size_t zmq::pgm_socket_t::send (unsigned char *data_, size_t data_len_) -{ - size_t nbytes = 0; - - const int status = pgm_send (sock, data_, data_len_, &nbytes); - - // We have to write all data as one packet. - if (nbytes > 0) { - zmq_assert (status == PGM_IO_STATUS_NORMAL); - zmq_assert (nbytes == data_len_); - } - else { - zmq_assert (status == PGM_IO_STATUS_RATE_LIMITED || - status == PGM_IO_STATUS_WOULD_BLOCK); - - if (status == PGM_IO_STATUS_RATE_LIMITED) - errno = ENOMEM; - else - errno = EBUSY; - } - - // Save return value. - last_tx_status = status; - - return nbytes; -} - -long zmq::pgm_socket_t::get_rx_timeout () -{ - if (last_rx_status != PGM_IO_STATUS_RATE_LIMITED && - last_rx_status != PGM_IO_STATUS_TIMER_PENDING) - return -1; - - struct timeval tv; - socklen_t optlen = sizeof (tv); - const bool rc = pgm_getsockopt (sock, IPPROTO_PGM, - last_rx_status == PGM_IO_STATUS_RATE_LIMITED ? PGM_RATE_REMAIN : - PGM_TIME_REMAIN, &tv, &optlen); - zmq_assert (rc); - - const long timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - - return timeout; -} - -long zmq::pgm_socket_t::get_tx_timeout () -{ - if (last_tx_status != PGM_IO_STATUS_RATE_LIMITED) - return -1; - - struct timeval tv; - socklen_t optlen = sizeof (tv); - const bool rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, - &optlen); - zmq_assert (rc); - - const long timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - - return timeout; -} - -// Return max TSDU size without fragmentation from current PGM transport. -size_t zmq::pgm_socket_t::get_max_tsdu_size () -{ - int max_tsdu = 0; - socklen_t optlen = sizeof (max_tsdu); - - bool rc = pgm_getsockopt (sock, IPPROTO_PGM, PGM_MSS, &max_tsdu, &optlen); - zmq_assert (rc); - zmq_assert (optlen == sizeof (max_tsdu)); - return (size_t) max_tsdu; -} - -// pgm_recvmsgv is called to fill the pgm_msgv array up to pgm_msgv_len. -// In subsequent calls data from pgm_msgv structure are returned. -ssize_t zmq::pgm_socket_t::receive (void **raw_data_, const pgm_tsi_t **tsi_) -{ - size_t raw_data_len = 0; - - // We just sent all data from pgm_transport_recvmsgv up - // and have to return 0 that another engine in this thread is scheduled. - if (nbytes_rec == nbytes_processed && nbytes_rec > 0) { - - // Reset all the counters. - nbytes_rec = 0; - nbytes_processed = 0; - pgm_msgv_processed = 0; - errno = EAGAIN; - return 0; - } - - // If we have are going first time or if we have processed all pgm_msgv_t - // structure previously read from the pgm socket. - if (nbytes_rec == nbytes_processed) { - - // Check program flow. - zmq_assert (pgm_msgv_processed == 0); - zmq_assert (nbytes_processed == 0); - zmq_assert (nbytes_rec == 0); - - // Receive a vector of Application Protocol Domain Unit's (APDUs) - // from the transport. - pgm_error_t *pgm_error = NULL; - - const int status = pgm_recvmsgv (sock, pgm_msgv, - pgm_msgv_len, MSG_ERRQUEUE, &nbytes_rec, &pgm_error); - - // Invalid parameters. - zmq_assert (status != PGM_IO_STATUS_ERROR); - - last_rx_status = status; - - // In a case when no ODATA/RDATA fired POLLIN event (SPM...) - // pgm_recvmsg returns PGM_IO_STATUS_TIMER_PENDING. - if (status == PGM_IO_STATUS_TIMER_PENDING) { - - zmq_assert (nbytes_rec == 0); - - // In case if no RDATA/ODATA caused POLLIN 0 is - // returned. - nbytes_rec = 0; - errno = EBUSY; - return 0; - } - - // Send SPMR, NAK, ACK is rate limited. - if (status == PGM_IO_STATUS_RATE_LIMITED) { - - zmq_assert (nbytes_rec == 0); - - // In case if no RDATA/ODATA caused POLLIN 0 is returned. - nbytes_rec = 0; - errno = ENOMEM; - return 0; - } - - // No peers and hence no incoming packets. - if (status == PGM_IO_STATUS_WOULD_BLOCK) { - - zmq_assert (nbytes_rec == 0); - - // In case if no RDATA/ODATA caused POLLIN 0 is returned. - nbytes_rec = 0; - errno = EAGAIN; - return 0; - } - - // Data loss. - if (status == PGM_IO_STATUS_RESET) { - - struct pgm_sk_buff_t* skb = pgm_msgv [0].msgv_skb [0]; - - // Save lost data TSI. - *tsi_ = &skb->tsi; - nbytes_rec = 0; - - // In case of dala loss -1 is returned. - errno = EINVAL; - pgm_free_skb (skb); - return -1; - } - - zmq_assert (status == PGM_IO_STATUS_NORMAL); - } - else - { - zmq_assert (pgm_msgv_processed <= pgm_msgv_len); - } - - // Zero byte payloads are valid in PGM, but not 0MQ protocol. - zmq_assert (nbytes_rec > 0); - - // Only one APDU per pgm_msgv_t structure is allowed. - zmq_assert (pgm_msgv [pgm_msgv_processed].msgv_len == 1); - - struct pgm_sk_buff_t* skb = - pgm_msgv [pgm_msgv_processed].msgv_skb [0]; - - // Take pointers from pgm_msgv_t structure. - *raw_data_ = skb->data; - raw_data_len = skb->len; - - // Save current TSI. - *tsi_ = &skb->tsi; - - // Move the the next pgm_msgv_t structure. - pgm_msgv_processed++; - zmq_assert (pgm_msgv_processed <= pgm_msgv_len); - nbytes_processed +=raw_data_len; - - return raw_data_len; -} - -void zmq::pgm_socket_t::process_upstream () -{ - pgm_msgv_t dummy_msg; - - size_t dummy_bytes = 0; - pgm_error_t *pgm_error = NULL; - - const int status = pgm_recvmsgv (sock, &dummy_msg, - 1, MSG_ERRQUEUE, &dummy_bytes, &pgm_error); - - // Invalid parameters. - zmq_assert (status != PGM_IO_STATUS_ERROR); - - // No data should be returned. - zmq_assert (dummy_bytes == 0 && (status == PGM_IO_STATUS_TIMER_PENDING || - status == PGM_IO_STATUS_RATE_LIMITED || - status == PGM_IO_STATUS_WOULD_BLOCK)); - - last_rx_status = status; - - if (status == PGM_IO_STATUS_TIMER_PENDING) - errno = EBUSY; - else - if (status == PGM_IO_STATUS_RATE_LIMITED) - errno = ENOMEM; - else - errno = EAGAIN; -} - -int zmq::pgm_socket_t::compute_sqns (int tpdu_) -{ - // Convert rate into B/ms. - uint64_t rate = uint64_t (options.rate) / 8; - - // Compute the size of the buffer in bytes. - uint64_t size = uint64_t (options.recovery_ivl) * rate; - - // Translate the size into number of packets. - uint64_t sqns = size / tpdu_; - - // Buffer should be able to hold at least one packet. - if (sqns == 0) - sqns = 1; - - return (int) sqns; -} - -#endif - diff --git a/src/pgm_socket.hpp b/src/pgm_socket.hpp deleted file mode 100644 index 9430932..0000000 --- a/src/pgm_socket.hpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __PGM_SOCKET_HPP_INCLUDED__ -#define __PGM_SOCKET_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_OPENPGM - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#define __PGM_WININT_H__ -#endif - -#include <pgm/pgm.h> - -#ifdef ZMQ_HAVE_OSX -#include <pgm/in.h> -#endif - -#include "fd.hpp" -#include "options.hpp" - -namespace zmq -{ - // Encapsulates PGM socket. - class pgm_socket_t - { - - public: - - // If receiver_ is true PGM transport is not generating SPM packets. - pgm_socket_t (bool receiver_, const options_t &options_); - - // Closes the transport. - ~pgm_socket_t (); - - // Initialize PGM network structures (GSI, GSRs). - int init (bool udp_encapsulation_, const char *network_); - - // Resolve PGM socket address. - static int init_address(const char *network_, struct pgm_addrinfo_t **addr, uint16_t *port_number); - - // Get receiver fds and store them into user allocated memory. - void get_receiver_fds (fd_t *receive_fd_, fd_t *waiting_pipe_fd_); - - // Get sender and receiver fds and store it to user allocated - // memory. Receive fd is used to process NAKs from peers. - void get_sender_fds (fd_t *send_fd_, fd_t *receive_fd_, - fd_t *rdata_notify_fd_, fd_t *pending_notify_fd_); - - // Send data as one APDU, transmit window owned memory. - size_t send (unsigned char *data_, size_t data_len_); - - // Returns max tsdu size without fragmentation. - size_t get_max_tsdu_size (); - - // Receive data from pgm socket. - ssize_t receive (void **data_, const pgm_tsi_t **tsi_); - - long get_rx_timeout (); - long get_tx_timeout (); - - // POLLIN on sender side should mean NAK or SPMR receiving. - // process_upstream function is used to handle such a situation. - void process_upstream (); - - private: - - // Compute size of the buffer based on rate and recovery interval. - int compute_sqns (int tpdu_); - - // OpenPGM transport. - pgm_sock_t* sock; - - int last_rx_status, last_tx_status; - - // Associated socket options. - options_t options; - - // true when pgm_socket should create receiving side. - bool receiver; - - // Array of pgm_msgv_t structures to store received data - // from the socket (pgm_transport_recvmsgv). - pgm_msgv_t *pgm_msgv; - - // Size of pgm_msgv array. - size_t pgm_msgv_len; - - // How many bytes were read from pgm socket. - size_t nbytes_rec; - - // How many bytes were processed from last pgm socket read. - size_t nbytes_processed; - - // How many messages from pgm_msgv were already sent up. - size_t pgm_msgv_processed; - }; -} -#endif - -#endif - diff --git a/src/pipe.cpp b/src/pipe.cpp deleted file mode 100644 index 6bbb53e..0000000 --- a/src/pipe.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <new> -#include <stddef.h> - -#include "pipe.hpp" -#include "err.hpp" - -#include "ypipe.hpp" -#include "ypipe_conflate.hpp" - -int zmq::pipepair (class object_t *parents_ [2], class pipe_t* pipes_ [2], - int hwms_ [2], bool conflate_ [2]) -{ - // Creates two pipe objects. These objects are connected by two ypipes, - // each to pass messages in one direction. - - typedef ypipe_t <msg_t, message_pipe_granularity> upipe_normal_t; - typedef ypipe_conflate_t <msg_t, message_pipe_granularity> upipe_conflate_t; - - pipe_t::upipe_t *upipe1; - if(conflate_ [0]) - upipe1 = new (std::nothrow) upipe_conflate_t (); - else - upipe1 = new (std::nothrow) upipe_normal_t (); - alloc_assert (upipe1); - - pipe_t::upipe_t *upipe2; - if(conflate_ [1]) - upipe2 = new (std::nothrow) upipe_conflate_t (); - else - upipe2 = new (std::nothrow) upipe_normal_t (); - alloc_assert (upipe2); - - pipes_ [0] = new (std::nothrow) pipe_t (parents_ [0], upipe1, upipe2, - hwms_ [1], hwms_ [0], conflate_ [0]); - alloc_assert (pipes_ [0]); - pipes_ [1] = new (std::nothrow) pipe_t (parents_ [1], upipe2, upipe1, - hwms_ [0], hwms_ [1], conflate_ [1]); - alloc_assert (pipes_ [1]); - - pipes_ [0]->set_peer (pipes_ [1]); - pipes_ [1]->set_peer (pipes_ [0]); - - return 0; -} - -zmq::pipe_t::pipe_t (object_t *parent_, upipe_t *inpipe_, upipe_t *outpipe_, - int inhwm_, int outhwm_, bool conflate_) : - object_t (parent_), - inpipe (inpipe_), - outpipe (outpipe_), - in_active (true), - out_active (true), - hwm (outhwm_), - lwm (compute_lwm (inhwm_)), - msgs_read (0), - msgs_written (0), - peers_msgs_read (0), - peer (NULL), - sink (NULL), - state (active), - delay (true), - conflate (conflate_) -{ -} - -zmq::pipe_t::~pipe_t () -{ -} - -void zmq::pipe_t::set_peer (pipe_t *peer_) -{ - // Peer can be set once only. - zmq_assert (!peer); - peer = peer_; -} - -void zmq::pipe_t::set_event_sink (i_pipe_events *sink_) -{ - // Sink can be set once only. - zmq_assert (!sink); - sink = sink_; -} - -void zmq::pipe_t::set_identity (const blob_t &identity_) -{ - identity = identity_; -} - -zmq::blob_t zmq::pipe_t::get_identity () -{ - return identity; -} - -bool zmq::pipe_t::check_read () -{ - if (unlikely (!in_active)) - return false; - if (unlikely (state != active && state != waiting_for_delimiter)) - return false; - - // Check if there's an item in the pipe. - if (!inpipe->check_read ()) { - in_active = false; - return false; - } - - // If the next item in the pipe is message delimiter, - // initiate termination process. - if (inpipe->probe (is_delimiter)) { - msg_t msg; - bool ok = inpipe->read (&msg); - zmq_assert (ok); - process_delimiter (); - return false; - } - - return true; -} - -bool zmq::pipe_t::read (msg_t *msg_) -{ - if (unlikely (!in_active)) - return false; - if (unlikely (state != active && state != waiting_for_delimiter)) - return false; - - if (!inpipe->read (msg_)) { - in_active = false; - return false; - } - - // If delimiter was read, start termination process of the pipe. - if (msg_->is_delimiter ()) { - process_delimiter (); - return false; - } - - if (!(msg_->flags () & msg_t::more)) - msgs_read++; - - if (lwm > 0 && msgs_read % lwm == 0) - send_activate_write (peer, msgs_read); - - return true; -} - -bool zmq::pipe_t::check_write () -{ - if (unlikely (!out_active || state != active)) - return false; - - bool full = hwm > 0 && msgs_written - peers_msgs_read == uint64_t (hwm); - - if (unlikely (full)) { - out_active = false; - return false; - } - - return true; -} - -bool zmq::pipe_t::write (msg_t *msg_) -{ - if (unlikely (!check_write ())) - return false; - - bool more = msg_->flags () & msg_t::more ? true : false; - outpipe->write (*msg_, more); - if (!more) - msgs_written++; - - return true; -} - -void zmq::pipe_t::rollback () -{ - // Remove incomplete message from the outbound pipe. - msg_t msg; - if (outpipe) { - while (outpipe->unwrite (&msg)) { - zmq_assert (msg.flags () & msg_t::more); - int rc = msg.close (); - errno_assert (rc == 0); - } - } -} - -void zmq::pipe_t::flush () -{ - // The peer does not exist anymore at this point. - if (state == term_ack_sent) - return; - - if (outpipe && !outpipe->flush ()) - send_activate_read (peer); -} - -void zmq::pipe_t::process_activate_read () -{ - if (!in_active && (state == active || state == waiting_for_delimiter)) { - in_active = true; - sink->read_activated (this); - } -} - -void zmq::pipe_t::process_activate_write (uint64_t msgs_read_) -{ - // Remember the peers's message sequence number. - peers_msgs_read = msgs_read_; - - if (!out_active && state == active) { - out_active = true; - sink->write_activated (this); - } -} - -void zmq::pipe_t::process_hiccup (void *pipe_) -{ - // Destroy old outpipe. Note that the read end of the pipe was already - // migrated to this thread. - zmq_assert (outpipe); - outpipe->flush (); - msg_t msg; - while (outpipe->read (&msg)) { - int rc = msg.close (); - errno_assert (rc == 0); - } - delete outpipe; - - // Plug in the new outpipe. - zmq_assert (pipe_); - outpipe = (upipe_t*) pipe_; - out_active = true; - - // If appropriate, notify the user about the hiccup. - if (state == active) - sink->hiccuped (this); -} - -void zmq::pipe_t::process_pipe_term () -{ - // This is the simple case of peer-induced termination. If there are no - // more pending messages to read, or if the pipe was configured to drop - // pending messages, we can move directly to the term_ack_sent state. - // Otherwise we'll hang up in waiting_for_delimiter state till all - // pending messages are read. - if (state == active) { - if (!delay) { - state = term_ack_sent; - outpipe = NULL; - send_pipe_term_ack (peer); - } - else - state = waiting_for_delimiter; - return; - } - - // Delimiter happened to arrive before the term command. Now we have the - // term command as well, so we can move straight to term_ack_sent state. - if (state == delimiter_received) { - state = term_ack_sent; - outpipe = NULL; - send_pipe_term_ack (peer); - return; - } - - // This is the case where both ends of the pipe are closed in parallel. - // We simply reply to the request by ack and continue waiting for our - // own ack. - if (state == term_req_sent1) { - state = term_req_sent2; - outpipe = NULL; - send_pipe_term_ack (peer); - return; - } - - // pipe_term is invalid in other states. - zmq_assert (false); -} - -void zmq::pipe_t::process_pipe_term_ack () -{ - // Notify the user that all the references to the pipe should be dropped. - zmq_assert (sink); - sink->pipe_terminated (this); - - // In term_ack_sent and term_req_sent2 states there's nothing to do. - // Simply deallocate the pipe. In term_req_sent1 state we have to ack - // the peer before deallocating this side of the pipe. - // All the other states are invalid. - if (state == term_req_sent1) { - outpipe = NULL; - send_pipe_term_ack (peer); - } - else - zmq_assert (state == term_ack_sent || state == term_req_sent2); - - // We'll deallocate the inbound pipe, the peer will deallocate the outbound - // pipe (which is an inbound pipe from its point of view). - // First, delete all the unread messages in the pipe. We have to do it by - // hand because msg_t doesn't have automatic destructor. Then deallocate - // the ypipe itself. - - if (!conflate) { - msg_t msg; - while (inpipe->read (&msg)) { - int rc = msg.close (); - errno_assert (rc == 0); - } - } - - delete inpipe; - - // Deallocate the pipe object - delete this; -} - -void zmq::pipe_t::set_nodelay () -{ - this->delay = false; -} - -void zmq::pipe_t::terminate (bool delay_) -{ - // Overload the value specified at pipe creation. - delay = delay_; - - // If terminate was already called, we can ignore the duplicit invocation. - if (state == term_req_sent1 || state == term_req_sent2) - return; - - // If the pipe is in the final phase of async termination, it's going to - // closed anyway. No need to do anything special here. - else - if (state == term_ack_sent) - return; - - // The simple sync termination case. Ask the peer to terminate and wait - // for the ack. - else - if (state == active) { - send_pipe_term (peer); - state = term_req_sent1; - } - - // There are still pending messages available, but the user calls - // 'terminate'. We can act as if all the pending messages were read. - else - if (state == waiting_for_delimiter && !delay) { - outpipe = NULL; - send_pipe_term_ack (peer); - state = term_ack_sent; - } - - // If there are pending messages still availabe, do nothing. - else - if (state == waiting_for_delimiter) { - } - - // We've already got delimiter, but not term command yet. We can ignore - // the delimiter and ack synchronously terminate as if we were in - // active state. - else - if (state == delimiter_received) { - send_pipe_term (peer); - state = term_req_sent1; - } - - // There are no other states. - else - zmq_assert (false); - - // Stop outbound flow of messages. - out_active = false; - - if (outpipe) { - - // Drop any unfinished outbound messages. - rollback (); - - // Write the delimiter into the pipe. Note that watermarks are not - // checked; thus the delimiter can be written even when the pipe is full. - msg_t msg; - msg.init_delimiter (); - outpipe->write (msg, false); - flush (); - } -} - -bool zmq::pipe_t::is_delimiter (msg_t &msg_) -{ - return msg_.is_delimiter (); -} - -int zmq::pipe_t::compute_lwm (int hwm_) -{ - // Compute the low water mark. Following point should be taken - // into consideration: - // - // 1. LWM has to be less than HWM. - // 2. LWM cannot be set to very low value (such as zero) as after filling - // the queue it would start to refill only after all the messages are - // read from it and thus unnecessarily hold the progress back. - // 3. LWM cannot be set to very high value (such as HWM-1) as it would - // result in lock-step filling of the queue - if a single message is - // read from a full queue, writer thread is resumed to write exactly one - // message to the queue and go back to sleep immediately. This would - // result in low performance. - // - // Given the 3. it would be good to keep HWM and LWM as far apart as - // possible to reduce the thread switching overhead to almost zero, - // say HWM-LWM should be max_wm_delta. - // - // That done, we still we have to account for the cases where - // HWM < max_wm_delta thus driving LWM to negative numbers. - // Let's make LWM 1/2 of HWM in such cases. - int result = (hwm_ > max_wm_delta * 2) ? - hwm_ - max_wm_delta : (hwm_ + 1) / 2; - - return result; -} - -void zmq::pipe_t::process_delimiter () -{ - zmq_assert (state == active - || state == waiting_for_delimiter); - - if (state == active) - state = delimiter_received; - else { - outpipe = NULL; - send_pipe_term_ack (peer); - state = term_ack_sent; - } -} - -void zmq::pipe_t::hiccup () -{ - // If termination is already under way do nothing. - if (state != active) - return; - - // We'll drop the pointer to the inpipe. From now on, the peer is - // responsible for deallocating it. - inpipe = NULL; - - // Create new inpipe. - if (conflate) - inpipe = new (std::nothrow) - ypipe_conflate_t <msg_t, message_pipe_granularity> (); - else - inpipe = new (std::nothrow) - ypipe_t <msg_t, message_pipe_granularity> (); - - alloc_assert (inpipe); - in_active = true; - - // Notify the peer about the hiccup. - send_hiccup (peer, (void*) inpipe); -} - -void zmq::pipe_t::set_hwms (int inhwm_, int outhwm_) -{ - lwm = compute_lwm (inhwm_); - hwm = outhwm_; -} diff --git a/src/pipe.hpp b/src/pipe.hpp deleted file mode 100644 index dfb35d3..0000000 --- a/src/pipe.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PIPE_HPP_INCLUDED__ -#define __ZMQ_PIPE_HPP_INCLUDED__ - -#include "msg.hpp" -#include "ypipe_base.hpp" -#include "config.hpp" -#include "object.hpp" -#include "stdint.hpp" -#include "array.hpp" -#include "blob.hpp" - -namespace zmq -{ - - class object_t; - class pipe_t; - - // Create a pipepair for bi-directional transfer of messages. - // First HWM is for messages passed from first pipe to the second pipe. - // Second HWM is for messages passed from second pipe to the first pipe. - // Delay specifies how the pipe behaves when the peer terminates. If true - // pipe receives all the pending messages before terminating, otherwise it - // terminates straight away. - // If conflate is true, only the most recently arrived message could be - // read (older messages are discarded) - int pipepair (zmq::object_t *parents_ [2], zmq::pipe_t* pipes_ [2], - int hwms_ [2], bool conflate_ [2]); - - struct i_pipe_events - { - virtual ~i_pipe_events () {} - - virtual void read_activated (zmq::pipe_t *pipe_) = 0; - virtual void write_activated (zmq::pipe_t *pipe_) = 0; - virtual void hiccuped (zmq::pipe_t *pipe_) = 0; - virtual void pipe_terminated (zmq::pipe_t *pipe_) = 0; - }; - - // Note that pipe can be stored in three different arrays. - // The array of inbound pipes (1), the array of outbound pipes (2) and - // the generic array of pipes to deallocate (3). - - class pipe_t : - public object_t, - public array_item_t <1>, - public array_item_t <2>, - public array_item_t <3> - { - // This allows pipepair to create pipe objects. - friend int pipepair (zmq::object_t *parents_ [2], zmq::pipe_t* pipes_ [2], - int hwms_ [2], bool conflate_ [2]); - - public: - - // Specifies the object to send events to. - void set_event_sink (i_pipe_events *sink_); - - // Pipe endpoint can store an opaque ID to be used by its clients. - void set_identity (const blob_t &identity_); - blob_t get_identity (); - - // Returns true if there is at least one message to read in the pipe. - bool check_read (); - - // Reads a message to the underlying pipe. - bool read (msg_t *msg_); - - // Checks whether messages can be written to the pipe. If writing - // the message would cause high watermark the function returns false. - bool check_write (); - - // Writes a message to the underlying pipe. Returns false if the - // message cannot be written because high watermark was reached. - bool write (msg_t *msg_); - - // Remove unfinished parts of the outbound message from the pipe. - void rollback (); - - // Flush the messages downsteam. - void flush (); - - // Temporaraily disconnects the inbound message stream and drops - // all the messages on the fly. Causes 'hiccuped' event to be generated - // in the peer. - void hiccup (); - - // Ensure the pipe wont block on receiving pipe_term. - void set_nodelay (); - - // Ask pipe to terminate. The termination will happen asynchronously - // and user will be notified about actual deallocation by 'terminated' - // event. If delay is true, the pending messages will be processed - // before actual shutdown. - void terminate (bool delay_); - - // set the high water marks. - void set_hwms (int inhwm_, int outhwm_); - - private: - - // Type of the underlying lock-free pipe. - typedef ypipe_base_t <msg_t, message_pipe_granularity> upipe_t; - - // Command handlers. - void process_activate_read (); - void process_activate_write (uint64_t msgs_read_); - void process_hiccup (void *pipe_); - void process_pipe_term (); - void process_pipe_term_ack (); - - // Handler for delimiter read from the pipe. - void process_delimiter (); - - // Constructor is private. Pipe can only be created using - // pipepair function. - pipe_t (object_t *parent_, upipe_t *inpipe_, upipe_t *outpipe_, - int inhwm_, int outhwm_, bool conflate_); - - // Pipepair uses this function to let us know about - // the peer pipe object. - void set_peer (pipe_t *pipe_); - - // Destructor is private. Pipe objects destroy themselves. - ~pipe_t (); - - // Underlying pipes for both directions. - upipe_t *inpipe; - upipe_t *outpipe; - - // Can the pipe be read from / written to? - bool in_active; - bool out_active; - - // High watermark for the outbound pipe. - int hwm; - - // Low watermark for the inbound pipe. - int lwm; - - // Number of messages read and written so far. - uint64_t msgs_read; - uint64_t msgs_written; - - // Last received peer's msgs_read. The actual number in the peer - // can be higher at the moment. - uint64_t peers_msgs_read; - - // The pipe object on the other side of the pipepair. - pipe_t *peer; - - // Sink to send events to. - i_pipe_events *sink; - - // States of the pipe endpoint: - // active: common state before any termination begins, - // delimiter_received: delimiter was read from pipe before - // term command was received, - // waiting_fo_delimiter: term command was already received - // from the peer but there are still pending messages to read, - // term_ack_sent: all pending messages were already read and - // all we are waiting for is ack from the peer, - // term_req_sent1: 'terminate' was explicitly called by the user, - // term_req_sent2: user called 'terminate' and then we've got - // term command from the peer as well. - enum { - active, - delimiter_received, - waiting_for_delimiter, - term_ack_sent, - term_req_sent1, - term_req_sent2 - } state; - - // If true, we receive all the pending inbound messages before - // terminating. If false, we terminate immediately when the peer - // asks us to. - bool delay; - - // Identity of the writer. Used uniquely by the reader side. - blob_t identity; - - // Returns true if the message is delimiter; false otherwise. - static bool is_delimiter (msg_t &msg_); - - // Computes appropriate low watermark from the given high watermark. - static int compute_lwm (int hwm_); - - bool conflate; - - // Disable copying. - pipe_t (const pipe_t&); - const pipe_t &operator = (const pipe_t&); - }; - -} - -#endif diff --git a/src/plain_mechanism.cpp b/src/plain_mechanism.cpp deleted file mode 100644 index b18655f..0000000 --- a/src/plain_mechanism.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include <string.h> -#include <string> - -#include "msg.hpp" -#include "session_base.hpp" -#include "err.hpp" -#include "plain_mechanism.hpp" -#include "wire.hpp" - -zmq::plain_mechanism_t::plain_mechanism_t (session_base_t *session_, - const std::string &peer_address_, - const options_t &options_) : - mechanism_t (options_), - session (session_), - peer_address (peer_address_), - expecting_zap_reply (false), - state (options.as_server? waiting_for_hello: sending_hello) -{ -} - -zmq::plain_mechanism_t::~plain_mechanism_t () -{ -} - -int zmq::plain_mechanism_t::next_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case sending_hello: - rc = produce_hello (msg_); - if (rc == 0) - state = waiting_for_welcome; - break; - case sending_welcome: - rc = produce_welcome (msg_); - if (rc == 0) - state = waiting_for_initiate; - break; - case sending_initiate: - rc = produce_initiate (msg_); - if (rc == 0) - state = waiting_for_ready; - break; - case sending_ready: - rc = produce_ready (msg_); - if (rc == 0) - state = ready; - break; - default: - errno = EAGAIN; - rc = -1; - } - return rc; -} - -int zmq::plain_mechanism_t::process_handshake_command (msg_t *msg_) -{ - int rc = 0; - - switch (state) { - case waiting_for_hello: - rc = process_hello (msg_); - if (rc == 0) - state = expecting_zap_reply? waiting_for_zap_reply: sending_welcome; - break; - case waiting_for_welcome: - rc = process_welcome (msg_); - if (rc == 0) - state = sending_initiate; - break; - case waiting_for_initiate: - rc = process_initiate (msg_); - if (rc == 0) - state = sending_ready; - break; - case waiting_for_ready: - rc = process_ready (msg_); - if (rc == 0) - state = ready; - break; - default: - errno = EPROTO; - rc = -1; - break; - } - if (rc == 0) { - rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - } - return rc; -} - -bool zmq::plain_mechanism_t::is_handshake_complete () const -{ - return state == ready; -} - -int zmq::plain_mechanism_t::zap_msg_available () -{ - if (state != waiting_for_zap_reply) { - errno = EFSM; - return -1; - } - const int rc = receive_and_process_zap_reply (); - if (rc == 0) - state = sending_welcome; - return rc; -} - -int zmq::plain_mechanism_t::produce_hello (msg_t *msg_) const -{ - const std::string username = options.plain_username; - zmq_assert (username.length () < 256); - - const std::string password = options.plain_password; - zmq_assert (password.length () < 256); - - const size_t command_size = 6 + 1 + username.length () - + 1 + password.length (); - - const int rc = msg_->init_size (command_size); - errno_assert (rc == 0); - - unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); - memcpy (ptr, "\x05HELLO", 6); - ptr += 6; - - *ptr++ = static_cast <unsigned char> (username.length ()); - memcpy (ptr, username.c_str (), username.length ()); - ptr += username.length (); - - *ptr++ = static_cast <unsigned char> (password.length ()); - memcpy (ptr, password.c_str (), password.length ()); - ptr += password.length (); - - return 0; -} - - -int zmq::plain_mechanism_t::process_hello (msg_t *msg_) -{ - const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); - size_t bytes_left = msg_->size (); - - if (bytes_left < 6 || memcmp (ptr, "\x05HELLO", 6)) { - errno = EPROTO; - return -1; - } - ptr += 6; - bytes_left -= 6; - - if (bytes_left < 1) { - errno = EPROTO; - return -1; - } - const size_t username_length = static_cast <size_t> (*ptr++); - bytes_left -= 1; - - if (bytes_left < username_length) { - errno = EPROTO; - return -1; - } - const std::string username = std::string ((char *) ptr, username_length); - ptr += username_length; - bytes_left -= username_length; - - if (bytes_left < 1) { - errno = EPROTO; - return -1; - } - const size_t password_length = static_cast <size_t> (*ptr++); - bytes_left -= 1; - - if (bytes_left < password_length) { - errno = EPROTO; - return -1; - } - const std::string password = std::string ((char *) ptr, password_length); - ptr += password_length; - bytes_left -= password_length; - - if (bytes_left > 0) { - errno = EPROTO; - return -1; - } - - // Use ZAP protocol (RFC 27) to authenticate the user. - int rc = session->zap_connect (); - if (rc == 0) { - send_zap_request (username, password); - rc = receive_and_process_zap_reply (); - if (rc != 0) { - if (errno != EAGAIN) - return -1; - expecting_zap_reply = true; - } - } - - return 0; -} - -int zmq::plain_mechanism_t::produce_welcome (msg_t *msg_) const -{ - const int rc = msg_->init_size (8); - errno_assert (rc == 0); - memcpy (msg_->data (), "\x07WELCOME", 8); - return 0; -} - -int zmq::plain_mechanism_t::process_welcome (msg_t *msg_) -{ - const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); - size_t bytes_left = msg_->size (); - - if (bytes_left != 8 || memcmp (ptr, "\x07WELCOME", 8)) { - errno = EPROTO; - return -1; - } - return 0; -} - -int zmq::plain_mechanism_t::produce_initiate (msg_t *msg_) const -{ - unsigned char * const command_buffer = (unsigned char *) malloc (512); - alloc_assert (command_buffer); - - unsigned char *ptr = command_buffer; - - // Add mechanism string - memcpy (ptr, "\x08INITIATE", 9); - ptr += 9; - - // Add socket type property - const char *socket_type = socket_type_string (options.type); - ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type)); - - // Add identity property - if (options.type == ZMQ_REQ - || options.type == ZMQ_DEALER - || options.type == ZMQ_ROUTER) { - ptr += add_property (ptr, "Identity", - options.identity, options.identity_size); - } - - const size_t command_size = ptr - command_buffer; - const int rc = msg_->init_size (command_size); - errno_assert (rc == 0); - memcpy (msg_->data (), command_buffer, command_size); - free (command_buffer); - - return 0; -} - -int zmq::plain_mechanism_t::process_initiate (msg_t *msg_) -{ - const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); - size_t bytes_left = msg_->size (); - - if (bytes_left < 9 || memcmp (ptr, "\x08INITIATE", 9)) { - errno = EPROTO; - return -1; - } - ptr += 9; - bytes_left -= 9; - return parse_metadata (ptr, bytes_left); -} - -int zmq::plain_mechanism_t::produce_ready (msg_t *msg_) const -{ - unsigned char * const command_buffer = (unsigned char *) malloc (512); - alloc_assert (command_buffer); - - unsigned char *ptr = command_buffer; - - // Add command name - memcpy (ptr, "\x05READY", 6); - ptr += 6; - - // Add socket type property - const char *socket_type = socket_type_string (options.type); - ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type)); - - // Add identity property - if (options.type == ZMQ_REQ - || options.type == ZMQ_DEALER - || options.type == ZMQ_ROUTER) { - ptr += add_property (ptr, "Identity", - options.identity, options.identity_size); - } - - const size_t command_size = ptr - command_buffer; - const int rc = msg_->init_size (command_size); - errno_assert (rc == 0); - memcpy (msg_->data (), command_buffer, command_size); - free (command_buffer); - - return 0; -} - -int zmq::plain_mechanism_t::process_ready (msg_t *msg_) -{ - const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); - size_t bytes_left = msg_->size (); - - if (bytes_left < 6 || memcmp (ptr, "\x05READY", 6)) { - errno = EPROTO; - return -1; - } - ptr += 6; - bytes_left -= 6; - return parse_metadata (ptr, bytes_left); -} - -void zmq::plain_mechanism_t::send_zap_request (const std::string &username, - const std::string &password) -{ - int rc; - msg_t msg; - - // Address delimiter frame - rc = msg.init (); - errno_assert (rc == 0); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Version frame - rc = msg.init_size (3); - errno_assert (rc == 0); - memcpy (msg.data (), "1.0", 3); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Request id frame - rc = msg.init_size (1); - errno_assert (rc == 0); - memcpy (msg.data (), "1", 1); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Domain frame - rc = msg.init_size (options.zap_domain.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Address frame - rc = msg.init_size (peer_address.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), peer_address.c_str (), peer_address.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Identity frame - rc = msg.init_size (options.identity_size); - errno_assert (rc == 0); - memcpy (msg.data (), options.identity, options.identity_size); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Mechanism frame - rc = msg.init_size (5); - errno_assert (rc == 0); - memcpy (msg.data (), "PLAIN", 5); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Username frame - rc = msg.init_size (username.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), username.c_str (), username.length ()); - msg.set_flags (msg_t::more); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); - - // Password frame - rc = msg.init_size (password.length ()); - errno_assert (rc == 0); - memcpy (msg.data (), password.c_str (), password.length ()); - rc = session->write_zap_msg (&msg); - errno_assert (rc == 0); -} - -int zmq::plain_mechanism_t::receive_and_process_zap_reply () -{ - int rc = 0; - msg_t msg [7]; // ZAP reply consists of 7 frames - - // Initialize all reply frames - for (int i = 0; i < 7; i++) { - rc = msg [i].init (); - errno_assert (rc == 0); - } - - for (int i = 0; i < 7; i++) { - rc = session->read_zap_msg (&msg [i]); - if (rc == -1) - break; - if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) { - errno = EPROTO; - rc = -1; - break; - } - } - - if (rc != 0) - goto error; - - // Address delimiter frame - if (msg [0].size () > 0) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Version frame - if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Request id frame - if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) { - rc = -1; - errno = EPROTO; - goto error; - } - - // Status code frame - if (msg [3].size () != 3 || memcmp (msg [3].data (), "200", 3)) { - rc = -1; - errno = EACCES; - goto error; - } - - // Process metadata frame - rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()), - msg [6].size ()); - -error: - for (int i = 0; i < 7; i++) { - const int rc2 = msg [i].close (); - errno_assert (rc2 == 0); - } - - return rc; -} diff --git a/src/plain_mechanism.hpp b/src/plain_mechanism.hpp deleted file mode 100644 index 02bb10f..0000000 --- a/src/plain_mechanism.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PLAIN_MECHANISM_HPP_INCLUDED__ -#define __ZMQ_PLAIN_MECHANISM_HPP_INCLUDED__ - -#include "mechanism.hpp" -#include "options.hpp" - -namespace zmq -{ - - class msg_t; - class session_base_t; - - class plain_mechanism_t : public mechanism_t - { - public: - - plain_mechanism_t (session_base_t *session_, - const std::string &peer_address_, - const options_t &options_); - virtual ~plain_mechanism_t (); - - // mechanism implementation - virtual int next_handshake_command (msg_t *msg_); - virtual int process_handshake_command (msg_t *msg_); - virtual int zap_msg_available (); - virtual bool is_handshake_complete () const; - - private: - - enum state_t { - sending_hello, - waiting_for_hello, - sending_welcome, - waiting_for_welcome, - sending_initiate, - waiting_for_initiate, - sending_ready, - waiting_for_ready, - waiting_for_zap_reply, - ready - }; - - session_base_t * const session; - - const std::string peer_address; - - // True iff we are awaiting reply from ZAP reply. - bool expecting_zap_reply; - - state_t state; - - int produce_hello (msg_t *msg_) const; - int produce_welcome (msg_t *msg_) const; - int produce_initiate (msg_t *msg_) const; - int produce_ready (msg_t *msg_) const; - - int process_hello (msg_t *msg_); - int process_welcome (msg_t *msg); - int process_ready (msg_t *msg_); - int process_initiate (msg_t *msg_); - - void send_zap_request (const std::string &username, - const std::string &password); - int receive_and_process_zap_reply (); - }; - -} - -#endif diff --git a/src/platform.hpp.in b/src/platform.hpp.in deleted file mode 100644 index 2fdac23..0000000 --- a/src/platform.hpp.in +++ /dev/null @@ -1,270 +0,0 @@ -/* src/platform.hpp.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the <alloca.h> header file. */ -#undef HAVE_ALLOCA_H - -/* Define to 1 if you have the <arpa/inet.h> header file. */ -#undef HAVE_ARPA_INET_H - -/* Define to 1 if you have the `clock_gettime' function. */ -#undef HAVE_CLOCK_GETTIME - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the <errno.h> header file. */ -#undef HAVE_ERRNO_H - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if you have the `freeifaddrs' function. */ -#undef HAVE_FREEIFADDRS - -/* Define to 1 if you have the `gethrtime' function. */ -#undef HAVE_GETHRTIME - -/* Define to 1 if you have the `getifaddrs' function. */ -#undef HAVE_GETIFADDRS - -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - -/* Define to 1 if you have the <ifaddrs.h> header file. */ -#undef HAVE_IFADDRS_H - -/* Define to 1 if you have the <inttypes.h> header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */ -#undef HAVE_LIBIPHLPAPI - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#undef HAVE_LIBPTHREAD - -/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */ -#undef HAVE_LIBRPCRT4 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#undef HAVE_LIBRT - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#undef HAVE_LIBSOCKET - -/* Define to 1 if you have the `sodium' library (-lsodium). */ -#undef HAVE_LIBSODIUM - -/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ -#undef HAVE_LIBWS2_32 - -/* Define to 1 if you have the <limits.h> header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the <memory.h> header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET - -/* Define to 1 if you have the <netinet/in.h> header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if you have the <netinet/tcp.h> header file. */ -#undef HAVE_NETINET_TCP_H - -/* Define to 1 if you have the `perror' function. */ -#undef HAVE_PERROR - -/* Define to 1 if you have the `socket' function. */ -#undef HAVE_SOCKET - -/* Define to 1 if stdbool.h conforms to C99. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the <stddef.h> header file. */ -#undef HAVE_STDDEF_H - -/* Define to 1 if you have the <stdint.h> header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the <stdlib.h> header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the <strings.h> header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the <string.h> header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the <sys/eventfd.h> header file. */ -#undef HAVE_SYS_EVENTFD_H - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the <sys/time.h> header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the <sys/types.h> header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the <sys/uio.h> header file. */ -#undef HAVE_SYS_UIO_H - -/* Define to 1 if you have the <time.h> header file. */ -#undef HAVE_TIME_H - -/* Define to 1 if you have the <unistd.h> header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the <windows.h> header file. */ -#undef HAVE_WINDOWS_H - -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#undef TIME_WITH_SYS_TIME - -/* Version number of package */ -#undef VERSION - -/* Force to use mutexes */ -#undef ZMQ_FORCE_MUTEXES - -/* Have AIX OS */ -#undef ZMQ_HAVE_AIX - -/* Have Android OS */ -#undef ZMQ_HAVE_ANDROID - -/* Have Cygwin */ -#undef ZMQ_HAVE_CYGWIN - -/* Have eventfd extension. */ -#undef ZMQ_HAVE_EVENTFD - -/* Have FreeBSD OS */ -#undef ZMQ_HAVE_FREEBSD - -/* Have HPUX OS */ -#undef ZMQ_HAVE_HPUX - -/* Have ifaddrs.h header. */ -#undef ZMQ_HAVE_IFADDRS - -/* Have Linux OS */ -#undef ZMQ_HAVE_LINUX - -/* Have MinGW32 */ -#undef ZMQ_HAVE_MINGW32 - -/* Have NetBSD OS */ -#undef ZMQ_HAVE_NETBSD - -/* Have OpenBSD OS */ -#undef ZMQ_HAVE_OPENBSD - -/* Have OpenPGM extension */ -#undef ZMQ_HAVE_OPENPGM - -/* Have DarwinOSX OS */ -#undef ZMQ_HAVE_OSX - -/* Have QNX Neutrino OS */ -#undef ZMQ_HAVE_QNXNTO - -/* Whether SOCK_CLOEXEC is defined and functioning. */ -#undef ZMQ_HAVE_SOCK_CLOEXEC - -/* Have Solaris OS */ -#undef ZMQ_HAVE_SOLARIS - -/* Whether SO_KEEPALIVE is supported. */ -#undef ZMQ_HAVE_SO_KEEPALIVE - -/* Whether TCP_KEEPALIVE is supported. */ -#undef ZMQ_HAVE_TCP_KEEPALIVE - -/* Whether TCP_KEEPCNT is supported. */ -#undef ZMQ_HAVE_TCP_KEEPCNT - -/* Whether TCP_KEEPIDLE is supported. */ -#undef ZMQ_HAVE_TCP_KEEPIDLE - -/* Whether TCP_KEEPINTVL is supported. */ -#undef ZMQ_HAVE_TCP_KEEPINTVL - -/* Have uio.h header. */ -#undef ZMQ_HAVE_UIO - -/* Have Windows OS */ -#undef ZMQ_HAVE_WINDOWS - -/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>, - <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT32_T - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -#undef size_t - -/* Define to `int' if <sys/types.h> does not define. */ -#undef ssize_t - -/* Define to the type of an unsigned integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef uint32_t - -/* Define to empty if the keyword `volatile' does not work. Warning: valid - code using `volatile' can become incorrect without. Disable with care. */ -#undef volatile diff --git a/src/poll.cpp b/src/poll.cpp deleted file mode 100644 index cf23afc..0000000 --- a/src/poll.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "poll.hpp" -#if defined ZMQ_USE_POLL - -#include <sys/types.h> -#include <sys/time.h> -#include <poll.h> -#include <algorithm> - -#include "poll.hpp" -#include "err.hpp" -#include "config.hpp" -#include "i_poll_events.hpp" - -zmq::poll_t::poll_t () : - retired (false), - stopping (false) -{ -} - -zmq::poll_t::~poll_t () -{ - worker.stop (); -} - -zmq::poll_t::handle_t zmq::poll_t::add_fd (fd_t fd_, i_poll_events *events_) -{ - // If the file descriptor table is too small expand it. - fd_table_t::size_type sz = fd_table.size (); - if (sz <= (fd_table_t::size_type) fd_) { - fd_table.resize (fd_ + 1); - while (sz != (fd_table_t::size_type) (fd_ + 1)) { - fd_table [sz].index = retired_fd; - ++sz; - } - } - - pollfd pfd = {fd_, 0, 0}; - pollset.push_back (pfd); - zmq_assert (fd_table [fd_].index == retired_fd); - - fd_table [fd_].index = pollset.size() - 1; - fd_table [fd_].events = events_; - - // Increase the load metric of the thread. - adjust_load (1); - - return fd_; -} - -void zmq::poll_t::rm_fd (handle_t handle_) -{ - fd_t index = fd_table [handle_].index; - zmq_assert (index != retired_fd); - - // Mark the fd as unused. - pollset [index].fd = retired_fd; - fd_table [handle_].index = retired_fd; - retired = true; - - // Decrease the load metric of the thread. - adjust_load (-1); -} - -void zmq::poll_t::set_pollin (handle_t handle_) -{ - int index = fd_table [handle_].index; - pollset [index].events |= POLLIN; -} - -void zmq::poll_t::reset_pollin (handle_t handle_) -{ - int index = fd_table [handle_].index; - pollset [index].events &= ~((short) POLLIN); -} - -void zmq::poll_t::set_pollout (handle_t handle_) -{ - int index = fd_table [handle_].index; - pollset [index].events |= POLLOUT; -} - -void zmq::poll_t::reset_pollout (handle_t handle_) -{ - int index = fd_table [handle_].index; - pollset [index].events &= ~((short) POLLOUT); -} - -void zmq::poll_t::start () -{ - worker.start (worker_routine, this); -} - -void zmq::poll_t::stop () -{ - stopping = true; -} - -int zmq::poll_t::max_fds () -{ - return -1; -} - -void zmq::poll_t::loop () -{ - while (!stopping) { - - // Execute any due timers. - int timeout = (int) execute_timers (); - - // Wait for events. - int rc = poll (&pollset [0], pollset.size (), timeout ? timeout : -1); - if (rc == -1) { - errno_assert (errno == EINTR); - continue; - } - - // If there are no events (i.e. it's a timeout) there's no point - // in checking the pollset. - if (rc == 0) - continue; - - for (pollset_t::size_type i = 0; i != pollset.size (); i++) { - - zmq_assert (!(pollset [i].revents & POLLNVAL)); - if (pollset [i].fd == retired_fd) - continue; - if (pollset [i].revents & (POLLERR | POLLHUP)) - fd_table [pollset [i].fd].events->in_event (); - if (pollset [i].fd == retired_fd) - continue; - if (pollset [i].revents & POLLOUT) - fd_table [pollset [i].fd].events->out_event (); - if (pollset [i].fd == retired_fd) - continue; - if (pollset [i].revents & POLLIN) - fd_table [pollset [i].fd].events->in_event (); - } - - // Clean up the pollset and update the fd_table accordingly. - if (retired) { - pollset_t::size_type i = 0; - while (i < pollset.size ()) { - if (pollset [i].fd == retired_fd) - pollset.erase (pollset.begin () + i); - else { - fd_table [pollset [i].fd].index = i; - i ++; - } - } - retired = false; - } - } -} - -void zmq::poll_t::worker_routine (void *arg_) -{ - ((poll_t*) arg_)->loop (); -} - -#endif diff --git a/src/poll.hpp b/src/poll.hpp deleted file mode 100644 index a331168..0000000 --- a/src/poll.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_POLL_HPP_INCLUDED__ -#define __ZMQ_POLL_HPP_INCLUDED__ - -// poller.hpp decides which polling mechanism to use. -#include "poller.hpp" -#if defined ZMQ_USE_POLL - -#include <poll.h> -#include <stddef.h> -#include <vector> - -#include "fd.hpp" -#include "thread.hpp" -#include "poller_base.hpp" - -namespace zmq -{ - - struct i_poll_events; - - // Implements socket polling mechanism using the POSIX.1-2001 - // poll() system call. - - class poll_t : public poller_base_t - { - public: - - typedef fd_t handle_t; - - poll_t (); - ~poll_t (); - - // "poller" concept. - handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void start (); - void stop (); - - static int max_fds (); - - private: - - // Main worker thread routine. - static void worker_routine (void *arg_); - - // Main event loop. - void loop (); - - struct fd_entry_t - { - fd_t index; - zmq::i_poll_events *events; - }; - - // This table stores data for registered descriptors. - typedef std::vector <fd_entry_t> fd_table_t; - fd_table_t fd_table; - - // Pollset to pass to the poll function. - typedef std::vector <pollfd> pollset_t; - pollset_t pollset; - - // If true, there's at least one retired event source. - bool retired; - - // If true, thread is in the process of shutting down. - bool stopping; - - // Handle of the physical thread doing the I/O work. - thread_t worker; - - poll_t (const poll_t&); - const poll_t &operator = (const poll_t&); - }; - - typedef poll_t poller_t; - -} - -#endif - -#endif diff --git a/src/poller.hpp b/src/poller.hpp deleted file mode 100644 index 2cad0e8..0000000 --- a/src/poller.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_POLLER_HPP_INCLUDED__ -#define __ZMQ_POLLER_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_FORCE_SELECT -#define ZMQ_USE_SELECT -#include "select.hpp" -#elif defined ZMQ_FORCE_POLL -#define ZMQ_USE_POLL -#include "poll.hpp" -#elif defined ZMQ_FORCE_EPOLL -#define ZMQ_USE_EPOLL -#include "epoll.hpp" -#elif defined ZMQ_FORCE_DEVPOLL -#define ZMQ_USE_DEVPOLL -#include "devpoll.hpp" -#elif defined ZMQ_FORCE_KQUEUE -#define ZMQ_USE_KQUEUE -#include "kqueue.hpp" -#elif defined ZMQ_HAVE_LINUX -#define ZMQ_USE_EPOLL -#include "epoll.hpp" -#elif defined ZMQ_HAVE_WINDOWS -#define ZMQ_USE_SELECT -#include "select.hpp" -#elif defined ZMQ_HAVE_FREEBSD -#define ZMQ_USE_KQUEUE -#include "kqueue.hpp" -#elif defined ZMQ_HAVE_OPENBSD -#define ZMQ_USE_KQUEUE -#include "kqueue.hpp" -#elif defined ZMQ_HAVE_NETBSD -#define ZMQ_USE_KQUEUE -#include "kqueue.hpp" -#elif defined ZMQ_HAVE_SOLARIS -#define ZMQ_USE_DEVPOLL -#include "devpoll.hpp" -#elif defined ZMQ_HAVE_OSX -#define ZMQ_USE_KQUEUE -#include "kqueue.hpp" -#elif defined ZMQ_HAVE_QNXNTO -#define ZMQ_USE_POLL -#include "poll.hpp" -#elif defined ZMQ_HAVE_AIX -#define ZMQ_USE_POLL -#include "poll.hpp" -#elif defined ZMQ_HAVE_HPUX -#define ZMQ_USE_DEVPOLL -#include "devpoll.hpp" -#elif defined ZMQ_HAVE_OPENVMS -#define ZMQ_USE_SELECT -#include "select.hpp" -#elif defined ZMQ_HAVE_CYGWIN -#define ZMQ_USE_SELECT -#include "select.hpp" -#else -#error Unsupported platform -#endif - -#endif diff --git a/src/poller_base.cpp b/src/poller_base.cpp deleted file mode 100644 index 5b9f36a..0000000 --- a/src/poller_base.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "poller_base.hpp" -#include "i_poll_events.hpp" -#include "err.hpp" - -zmq::poller_base_t::poller_base_t () -{ -} - -zmq::poller_base_t::~poller_base_t () -{ - // Make sure there is no more load on the shutdown. - zmq_assert (get_load () == 0); -} - -int zmq::poller_base_t::get_load () -{ - return load.get (); -} - -void zmq::poller_base_t::adjust_load (int amount_) -{ - if (amount_ > 0) - load.add (amount_); - else - if (amount_ < 0) - load.sub (-amount_); -} - -void zmq::poller_base_t::add_timer (int timeout_, i_poll_events *sink_, int id_) -{ - uint64_t expiration = clock.now_ms () + timeout_; - timer_info_t info = {sink_, id_}; - timers.insert (timers_t::value_type (expiration, info)); -} - -void zmq::poller_base_t::cancel_timer (i_poll_events *sink_, int id_) -{ - // Complexity of this operation is O(n). We assume it is rarely used. - for (timers_t::iterator it = timers.begin (); it != timers.end (); ++it) - if (it->second.sink == sink_ && it->second.id == id_) { - timers.erase (it); - return; - } - - // Timer not found. - zmq_assert (false); -} - -uint64_t zmq::poller_base_t::execute_timers () -{ - // Fast track. - if (timers.empty ()) - return 0; - - // Get the current time. - uint64_t current = clock.now_ms (); - - // Execute the timers that are already due. - timers_t::iterator it = timers.begin (); - while (it != timers.end ()) { - - // If we have to wait to execute the item, same will be true about - // all the following items (multimap is sorted). Thus we can stop - // checking the subsequent timers and return the time to wait for - // the next timer (at least 1ms). - if (it->first > current) - return it->first - current; - - // Trigger the timer. - it->second.sink->timer_event (it->second.id); - - // Remove it from the list of active timers. - timers_t::iterator o = it; - ++it; - timers.erase (o); - } - - // There are no more timers. - return 0; -} diff --git a/src/poller_base.hpp b/src/poller_base.hpp deleted file mode 100644 index c122ab8..0000000 --- a/src/poller_base.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_POLLER_BASE_HPP_INCLUDED__ -#define __ZMQ_POLLER_BASE_HPP_INCLUDED__ - -#include <map> - -#include "clock.hpp" -#include "atomic_counter.hpp" - -namespace zmq -{ - - struct i_poll_events; - - class poller_base_t - { - public: - - poller_base_t (); - virtual ~poller_base_t (); - - // Returns load of the poller. Note that this function can be - // invoked from a different thread! - int get_load (); - - // Add a timeout to expire in timeout_ milliseconds. After the - // expiration timer_event on sink_ object will be called with - // argument set to id_. - void add_timer (int timeout_, zmq::i_poll_events *sink_, int id_); - - // Cancel the timer created by sink_ object with ID equal to id_. - void cancel_timer (zmq::i_poll_events *sink_, int id_); - - protected: - - // Called by individual poller implementations to manage the load. - void adjust_load (int amount_); - - // Executes any timers that are due. Returns number of milliseconds - // to wait to match the next timer or 0 meaning "no timers". - uint64_t execute_timers (); - - private: - - // Clock instance private to this I/O thread. - clock_t clock; - - // List of active timers. - struct timer_info_t - { - zmq::i_poll_events *sink; - int id; - }; - typedef std::multimap <uint64_t, timer_info_t> timers_t; - timers_t timers; - - // Load of the poller. Currently the number of file descriptors - // registered. - atomic_counter_t load; - - poller_base_t (const poller_base_t&); - const poller_base_t &operator = (const poller_base_t&); - }; - -} - -#endif diff --git a/src/precompiled.cpp b/src/precompiled.cpp deleted file mode 100644 index b8183f9..0000000 --- a/src/precompiled.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "precompiled.hpp" diff --git a/src/precompiled.hpp b/src/precompiled.hpp deleted file mode 100644 index 598e59e..0000000 --- a/src/precompiled.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PRECOMPILED_HPP_INCLUDED__ -#define __ZMQ_PRECOMPILED_HPP_INCLUDED__ - -#ifdef _MSC_VER - -// Windows headers -#include "platform.hpp" -#include "windows.hpp" -#include <fcntl.h> -#include <intrin.h> -#include <io.h> -#include <rpc.h> -#include <sys/stat.h> - -// standard C++ headers -#include <algorithm> -#include <map> -#include <set> -#include <string> -#include <vector> - -// 0MQ definitions and exported functions -#include "../include/zmq.h" - -#endif // _MSC_VER - -#endif diff --git a/src/proxy.cpp b/src/proxy.cpp deleted file mode 100644 index 1a172c1..0000000 --- a/src/proxy.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stddef.h> -#include "platform.hpp" -#include "proxy.hpp" -#include "likely.hpp" - -#if defined ZMQ_FORCE_SELECT -#define ZMQ_POLL_BASED_ON_SELECT -#elif defined ZMQ_FORCE_POLL -#define ZMQ_POLL_BASED_ON_POLL -#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\ - defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\ - defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\ - defined ZMQ_HAVE_NETBSD -#define ZMQ_POLL_BASED_ON_POLL -#elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS ||\ - defined ZMQ_HAVE_CYGWIN -#define ZMQ_POLL_BASED_ON_SELECT -#endif - -// On AIX platform, poll.h has to be included first to get consistent -// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents' -// instead of 'events' and 'revents' and defines macros to map from POSIX-y -// names to AIX-specific names). -#if defined ZMQ_POLL_BASED_ON_POLL -#include <poll.h> -#endif - -// These headers end up pulling in zmq.h somewhere in their include -// dependency chain -#include "socket_base.hpp" -#include "err.hpp" - -// zmq.h must be included *after* poll.h for AIX to build properly -#include "../include/zmq.h" - - -int zmq::proxy ( - class socket_base_t *frontend_, - class socket_base_t *backend_, - class socket_base_t *capture_) -{ - msg_t msg; - int rc = msg.init (); - if (rc != 0) - return -1; - - // The algorithm below assumes ratio of requests and replies processed - // under full load to be 1:1. - - int more; - size_t moresz; - zmq_pollitem_t items [] = { - { frontend_, 0, ZMQ_POLLIN, 0 }, - { backend_, 0, ZMQ_POLLIN, 0 } - }; - while (true) { - // Wait while there are either requests or replies to process. - rc = zmq_poll (&items [0], 2, -1); - if (unlikely (rc < 0)) - return -1; - - // Process a request - if (items [0].revents & ZMQ_POLLIN) { - while (true) { - rc = frontend_->recv (&msg, 0); - if (unlikely (rc < 0)) - return -1; - - moresz = sizeof more; - rc = frontend_->getsockopt (ZMQ_RCVMORE, &more, &moresz); - if (unlikely (rc < 0)) - return -1; - - // Copy message to capture socket if any - if (capture_) { - msg_t ctrl; - rc = ctrl.init (); - if (unlikely (rc < 0)) - return -1; - rc = ctrl.copy (msg); - if (unlikely (rc < 0)) - return -1; - rc = capture_->send (&ctrl, more? ZMQ_SNDMORE: 0); - if (unlikely (rc < 0)) - return -1; - } - rc = backend_->send (&msg, more? ZMQ_SNDMORE: 0); - if (unlikely (rc < 0)) - return -1; - if (more == 0) - break; - } - } - // Process a reply - if (items [1].revents & ZMQ_POLLIN) { - while (true) { - rc = backend_->recv (&msg, 0); - if (unlikely (rc < 0)) - return -1; - - moresz = sizeof more; - rc = backend_->getsockopt (ZMQ_RCVMORE, &more, &moresz); - if (unlikely (rc < 0)) - return -1; - - // Copy message to capture socket if any - if (capture_) { - msg_t ctrl; - rc = ctrl.init (); - if (unlikely (rc < 0)) - return -1; - rc = ctrl.copy (msg); - if (unlikely (rc < 0)) - return -1; - rc = capture_->send (&ctrl, more? ZMQ_SNDMORE: 0); - if (unlikely (rc < 0)) - return -1; - } - rc = frontend_->send (&msg, more? ZMQ_SNDMORE: 0); - if (unlikely (rc < 0)) - return -1; - if (more == 0) - break; - } - } - - } - return 0; -} diff --git a/src/proxy.hpp b/src/proxy.hpp deleted file mode 100644 index eaf164f..0000000 --- a/src/proxy.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PROXY_HPP_INCLUDED__ -#define __ZMQ_PROXY_HPP_INCLUDED__ - -namespace zmq -{ - int proxy ( - class socket_base_t *frontend_, - class socket_base_t *backend_, - class socket_base_t *control_); -} - -#endif diff --git a/src/pub.cpp b/src/pub.cpp deleted file mode 100644 index e84f3c3..0000000 --- a/src/pub.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "pub.hpp" -#include "msg.hpp" - -zmq::pub_t::pub_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - xpub_t (parent_, tid_, sid_) -{ - options.type = ZMQ_PUB; -} - -zmq::pub_t::~pub_t () -{ -} - -int zmq::pub_t::xrecv (class msg_t *) -{ - // Messages cannot be received from PUB socket. - errno = ENOTSUP; - return -1; -} - -bool zmq::pub_t::xhas_in () -{ - return false; -} diff --git a/src/pub.hpp b/src/pub.hpp deleted file mode 100644 index 4fe3a79..0000000 --- a/src/pub.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PUB_HPP_INCLUDED__ -#define __ZMQ_PUB_HPP_INCLUDED__ - -#include "xpub.hpp" - -namespace zmq -{ - - class ctx_t; - class io_thread_t; - class socket_base_t; - class msg_t; - - class pub_t : public xpub_t - { - public: - - pub_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~pub_t (); - - // Implementations of virtual functions from socket_base_t. - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - - private: - - pub_t (const pub_t&); - const pub_t &operator = (const pub_t&); - }; - -} - -#endif diff --git a/src/pull.cpp b/src/pull.cpp deleted file mode 100644 index a7d246d..0000000 --- a/src/pull.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "pull.hpp" -#include "err.hpp" -#include "msg.hpp" -#include "pipe.hpp" - -zmq::pull_t::pull_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_) -{ - options.type = ZMQ_PULL; -} - -zmq::pull_t::~pull_t () -{ -} - -void zmq::pull_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void)subscribe_to_all_; - - zmq_assert (pipe_); - fq.attach (pipe_); -} - -void zmq::pull_t::xread_activated (pipe_t *pipe_) -{ - fq.activated (pipe_); -} - -void zmq::pull_t::xpipe_terminated (pipe_t *pipe_) -{ - fq.pipe_terminated (pipe_); -} - -int zmq::pull_t::xrecv (msg_t *msg_) -{ - return fq.recv (msg_); -} - -bool zmq::pull_t::xhas_in () -{ - return fq.has_in (); -} diff --git a/src/pull.hpp b/src/pull.hpp deleted file mode 100644 index bd0f68b..0000000 --- a/src/pull.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PULL_HPP_INCLUDED__ -#define __ZMQ_PULL_HPP_INCLUDED__ - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "fq.hpp" - -namespace zmq -{ - - class ctx_t; - class pipe_t; - class msg_t; - class io_thread_t; - - class pull_t : - public socket_base_t - { - public: - - pull_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~pull_t (); - - protected: - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - void xread_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - - // Fair queueing object for inbound pipes. - fq_t fq; - - pull_t (const pull_t&); - const pull_t &operator = (const pull_t&); - - }; - -} - -#endif diff --git a/src/push.cpp b/src/push.cpp deleted file mode 100644 index 673d2be..0000000 --- a/src/push.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "push.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::push_t::push_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_) -{ - options.type = ZMQ_PUSH; -} - -zmq::push_t::~push_t () -{ -} - -void zmq::push_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void)subscribe_to_all_; - - zmq_assert (pipe_); - lb.attach (pipe_); -} - -void zmq::push_t::xwrite_activated (pipe_t *pipe_) -{ - lb.activated (pipe_); -} - -void zmq::push_t::xpipe_terminated (pipe_t *pipe_) -{ - lb.pipe_terminated (pipe_); -} - -int zmq::push_t::xsend (msg_t *msg_) -{ - return lb.send (msg_); -} - -bool zmq::push_t::xhas_out () -{ - return lb.has_out (); -} diff --git a/src/push.hpp b/src/push.hpp deleted file mode 100644 index 0f587b8..0000000 --- a/src/push.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_PUSH_HPP_INCLUDED__ -#define __ZMQ_PUSH_HPP_INCLUDED__ - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "lb.hpp" - -namespace zmq -{ - - class ctx_t; - class pipe_t; - class msg_t; - class io_thread_t; - - class push_t : - public socket_base_t - { - public: - - push_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~push_t (); - - protected: - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsend (zmq::msg_t *msg_); - bool xhas_out (); - void xwrite_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - - // Load balancer managing the outbound pipes. - lb_t lb; - - push_t (const push_t&); - const push_t &operator = (const push_t&); - }; - -} - -#endif diff --git a/src/random.cpp b/src/random.cpp deleted file mode 100644 index 06ed1de..0000000 --- a/src/random.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#endif - -#include "random.hpp" -#include "stdint.hpp" -#include "clock.hpp" - -void zmq::seed_random () -{ -#if defined ZMQ_HAVE_WINDOWS - int pid = (int) GetCurrentProcessId (); -#else - int pid = (int) getpid (); -#endif - srand ((unsigned int) (clock_t::now_us () + pid)); -} - -uint32_t zmq::generate_random () -{ - // Compensate for the fact that rand() returns signed integer. - uint32_t low = (uint32_t) rand (); - uint32_t high = (uint32_t) rand (); - high <<= (sizeof (int) * 8 - 1); - return high | low; -} - diff --git a/src/random.hpp b/src/random.hpp deleted file mode 100644 index 78ed55b..0000000 --- a/src/random.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_RANDOM_HPP_INCLUDED__ -#define __ZMQ_RANDOM_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - // Seeds the random number generator. - void seed_random (); - - // Generates random value. - uint32_t generate_random (); - -} - -#endif diff --git a/src/raw_decoder.cpp b/src/raw_decoder.cpp deleted file mode 100644 index fe05ac5..0000000 --- a/src/raw_decoder.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> -#include <string.h> - -#include "platform.hpp" -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "raw_decoder.hpp" -#include "err.hpp" - -zmq::raw_decoder_t::raw_decoder_t (size_t bufsize_) : - bufsize (bufsize_) -{ - int rc = in_progress.init (); - errno_assert (rc == 0); - - buffer = (unsigned char *) malloc (bufsize); - alloc_assert (buffer); -} - -zmq::raw_decoder_t::~raw_decoder_t () -{ - int rc = in_progress.close (); - errno_assert (rc == 0); - - free (buffer); -} - -void zmq::raw_decoder_t::get_buffer (unsigned char **data_, size_t *size_) -{ - *data_ = buffer; - *size_ = bufsize; -} - -int zmq::raw_decoder_t::decode (const uint8_t *data_, size_t size_, - size_t &bytes_used_) -{ - int rc = in_progress.init_size (size_); - errno_assert (rc != -1); - memcpy (in_progress.data (), data_, size_); - bytes_used_ = size_; - return 1; -} diff --git a/src/raw_decoder.hpp b/src/raw_decoder.hpp deleted file mode 100644 index 9f23156..0000000 --- a/src/raw_decoder.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_RAW_DECODER_HPP_INCLUDED__ -#define __ZMQ_RAW_DECODER_HPP_INCLUDED__ - -#include "err.hpp" -#include "msg.hpp" -#include "i_decoder.hpp" -#include "stdint.hpp" - -namespace zmq -{ - - // Decoder for 0MQ v1 framing protocol. Converts data stream into messages. - - class raw_decoder_t : public i_decoder - { - public: - - raw_decoder_t (size_t bufsize_); - virtual ~raw_decoder_t (); - - // i_decoder interface. - - virtual void get_buffer (unsigned char **data_, size_t *size_); - - virtual int decode (const unsigned char *data_, size_t size_, - size_t &processed); - - virtual msg_t *msg () { return &in_progress; } - - - private: - - - msg_t in_progress; - - const int64_t bufsize; - - unsigned char *buffer; - - raw_decoder_t (const raw_decoder_t&); - void operator = (const raw_decoder_t&); - }; - -} - -#endif - diff --git a/src/raw_encoder.cpp b/src/raw_encoder.cpp deleted file mode 100644 index dbf8545..0000000 --- a/src/raw_encoder.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "encoder.hpp" -#include "raw_encoder.hpp" -#include "likely.hpp" -#include "wire.hpp" - -zmq::raw_encoder_t::raw_encoder_t (size_t bufsize_) : - encoder_base_t <raw_encoder_t> (bufsize_) -{ - // Write 0 bytes to the batch and go to message_ready state. - next_step (NULL, 0, &raw_encoder_t::raw_message_ready, true); -} - -zmq::raw_encoder_t::~raw_encoder_t () -{ -} - -void zmq::raw_encoder_t::raw_message_ready () -{ - next_step (in_progress->data (), in_progress->size (), - &raw_encoder_t::raw_message_ready, true); -} diff --git a/src/raw_encoder.hpp b/src/raw_encoder.hpp deleted file mode 100644 index fec36d3..0000000 --- a/src/raw_encoder.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_RAW_ENCODER_HPP_INCLUDED__ -#define __ZMQ_RAW_ENCODER_HPP_INCLUDED__ - -#if defined(_MSC_VER) -#ifndef NOMINMAX -#define NOMINMAX -#endif -#endif - -#include <stddef.h> -#include <string.h> -#include <stdlib.h> -#include <algorithm> - -#include "err.hpp" -#include "msg.hpp" -#include "i_encoder.hpp" - -namespace zmq -{ - - // Encoder for 0MQ framing protocol. Converts messages into data batches. - - class raw_encoder_t : public encoder_base_t <raw_encoder_t> - { - public: - - raw_encoder_t (size_t bufsize_); - ~raw_encoder_t (); - - private: - - void raw_message_ready (); - - raw_encoder_t (const raw_encoder_t&); - const raw_encoder_t &operator = (const raw_encoder_t&); - }; -} - -#endif - diff --git a/src/reaper.cpp b/src/reaper.cpp deleted file mode 100644 index 62fa8e8..0000000 --- a/src/reaper.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "reaper.hpp" -#include "socket_base.hpp" -#include "err.hpp" - -zmq::reaper_t::reaper_t (class ctx_t *ctx_, uint32_t tid_) : - object_t (ctx_, tid_), - sockets (0), - terminating (false) -{ - poller = new (std::nothrow) poller_t; - alloc_assert (poller); - - mailbox_handle = poller->add_fd (mailbox.get_fd (), this); - poller->set_pollin (mailbox_handle); - -#ifdef HAVE_FORK - pid = getpid(); -#endif -} - -zmq::reaper_t::~reaper_t () -{ - delete poller; -} - -zmq::mailbox_t *zmq::reaper_t::get_mailbox () -{ - return &mailbox; -} - -void zmq::reaper_t::start () -{ - // Start the thread. - poller->start (); -} - -void zmq::reaper_t::stop () -{ - send_stop (); -} - -void zmq::reaper_t::in_event () -{ - while (true) { -#ifdef HAVE_FORK - if (unlikely(pid != getpid())) - { - //printf("zmq::reaper_t::in_event return in child process %d\n", (int)getpid()); - return; - } -#endif - - // Get the next command. If there is none, exit. - command_t cmd; - int rc = mailbox.recv (&cmd, 0); - if (rc != 0 && errno == EINTR) - continue; - if (rc != 0 && errno == EAGAIN) - break; - errno_assert (rc == 0); - - // Process the command. - cmd.destination->process_command (cmd); - } -} - -void zmq::reaper_t::out_event () -{ - zmq_assert (false); -} - -void zmq::reaper_t::timer_event (int) -{ - zmq_assert (false); -} - -void zmq::reaper_t::process_stop () -{ - terminating = true; - - // If there are no sockets being reaped finish immediately. - if (!sockets) { - send_done (); - poller->rm_fd (mailbox_handle); - poller->stop (); - } -} - -void zmq::reaper_t::process_reap (socket_base_t *socket_) -{ - // Add the socket to the poller. - socket_->start_reaping (poller); - - ++sockets; -} - -void zmq::reaper_t::process_reaped () -{ - --sockets; - - // If reaped was already asked to terminate and there are no more sockets, - // finish immediately. - if (!sockets && terminating) { - send_done (); - poller->rm_fd (mailbox_handle); - poller->stop (); - } -} diff --git a/src/reaper.hpp b/src/reaper.hpp deleted file mode 100644 index 5e6b3ad..0000000 --- a/src/reaper.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_REAPER_HPP_INCLUDED__ -#define __ZMQ_REAPER_HPP_INCLUDED__ - -#include "object.hpp" -#include "mailbox.hpp" -#include "poller.hpp" -#include "i_poll_events.hpp" - -namespace zmq -{ - - class ctx_t; - class socket_base_t; - - class reaper_t : public object_t, public i_poll_events - { - public: - - reaper_t (zmq::ctx_t *ctx_, uint32_t tid_); - ~reaper_t (); - - mailbox_t *get_mailbox (); - - void start (); - void stop (); - - // i_poll_events implementation. - void in_event (); - void out_event (); - void timer_event (int id_); - - private: - - // Command handlers. - void process_stop (); - void process_reap (zmq::socket_base_t *socket_); - void process_reaped (); - - // Reaper thread accesses incoming commands via this mailbox. - mailbox_t mailbox; - - // Handle associated with mailbox' file descriptor. - poller_t::handle_t mailbox_handle; - - // I/O multiplexing is performed using a poller object. - poller_t *poller; - - // Number of sockets being reaped at the moment. - int sockets; - - // If true, we were already asked to terminate. - bool terminating; - - reaper_t (const reaper_t&); - const reaper_t &operator = (const reaper_t&); - -#ifdef HAVE_FORK - // the process that created this context. Used to detect forking. - pid_t pid; -#endif - }; - -} - -#endif diff --git a/src/rep.cpp b/src/rep.cpp deleted file mode 100644 index a45e635..0000000 --- a/src/rep.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "rep.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::rep_t::rep_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - router_t (parent_, tid_, sid_), - sending_reply (false), - request_begins (true) -{ - options.type = ZMQ_REP; -} - -zmq::rep_t::~rep_t () -{ -} - -int zmq::rep_t::xsend (msg_t *msg_) -{ - // If we are in the middle of receiving a request, we cannot send reply. - if (!sending_reply) { - errno = EFSM; - return -1; - } - - bool more = msg_->flags () & msg_t::more ? true : false; - - // Push message to the reply pipe. - int rc = router_t::xsend (msg_); - if (rc != 0) - return rc; - - // If the reply is complete flip the FSM back to request receiving state. - if (!more) - sending_reply = false; - - return 0; -} - -int zmq::rep_t::xrecv (msg_t *msg_) -{ - // If we are in middle of sending a reply, we cannot receive next request. - if (sending_reply) { - errno = EFSM; - return -1; - } - - // First thing to do when receiving a request is to copy all the labels - // to the reply pipe. - if (request_begins) { - while (true) { - int rc = router_t::xrecv (msg_); - if (rc != 0) - return rc; - - if ((msg_->flags () & msg_t::more)) { - // Empty message part delimits the traceback stack. - bool bottom = (msg_->size () == 0); - - // Push it to the reply pipe. - rc = router_t::xsend (msg_); - errno_assert (rc == 0); - - if (bottom) - break; - } - else { - // If the traceback stack is malformed, discard anything - // already sent to pipe (we're at end of invalid message). - rc = router_t::rollback (); - errno_assert (rc == 0); - } - } - request_begins = false; - } - - // Get next message part to return to the user. - int rc = router_t::xrecv (msg_); - if (rc != 0) - return rc; - - // If whole request is read, flip the FSM to reply-sending state. - if (!(msg_->flags () & msg_t::more)) { - sending_reply = true; - request_begins = true; - } - - return 0; -} - -bool zmq::rep_t::xhas_in () -{ - if (sending_reply) - return false; - - return router_t::xhas_in (); -} - -bool zmq::rep_t::xhas_out () -{ - if (!sending_reply) - return false; - - return router_t::xhas_out (); -} diff --git a/src/rep.hpp b/src/rep.hpp deleted file mode 100644 index 027b464..0000000 --- a/src/rep.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_REP_HPP_INCLUDED__ -#define __ZMQ_REP_HPP_INCLUDED__ - -#include "router.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class io_thread_t; - class socket_base_t; - - class rep_t : public router_t - { - public: - - rep_t (zmq::ctx_t *parent_, uint32_t tid_, int sid); - ~rep_t (); - - // Overloads of functions from socket_base_t. - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - - private: - - // If true, we are in process of sending the reply. If false we are - // in process of receiving a request. - bool sending_reply; - - // If true, we are starting to receive a request. The beginning - // of the request is the backtrace stack. - bool request_begins; - - rep_t (const rep_t&); - const rep_t &operator = (const rep_t&); - - }; - -} - -#endif diff --git a/src/req.cpp b/src/req.cpp deleted file mode 100644 index 0fa36aa..0000000 --- a/src/req.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "req.hpp" -#include "err.hpp" -#include "msg.hpp" -#include "wire.hpp" -#include "random.hpp" -#include "likely.hpp" - -zmq::req_t::req_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - dealer_t (parent_, tid_, sid_), - receiving_reply (false), - message_begins (true), - reply_pipe (NULL), - request_id_frames_enabled (false), - request_id (generate_random()), - strict (true) -{ - options.type = ZMQ_REQ; -} - -zmq::req_t::~req_t () -{ -} - -int zmq::req_t::xsend (msg_t *msg_) -{ - // If we've sent a request and we still haven't got the reply, - // we can't send another request unless the strict option is disabled. - if (receiving_reply) { - if (strict) { - errno = EFSM; - return -1; - } - - if (reply_pipe) - reply_pipe->terminate (false); - receiving_reply = false; - message_begins = true; - } - - // First part of the request is the request identity. - if (message_begins) { - reply_pipe = NULL; - - if (request_id_frames_enabled) { - request_id++; - - msg_t id; - int rc = id.init_data (&request_id, sizeof (request_id), NULL, NULL); - errno_assert (rc == 0); - id.set_flags (msg_t::more); - - rc = dealer_t::sendpipe (&id, &reply_pipe); - if (rc != 0) - return -1; - } - - msg_t bottom; - int rc = bottom.init (); - errno_assert (rc == 0); - bottom.set_flags (msg_t::more); - - rc = dealer_t::sendpipe (&bottom, &reply_pipe); - if (rc != 0) - return -1; - assert (reply_pipe); - - message_begins = false; - - // Eat all currently avaliable messages before the request is fully - // sent. This is done to avoid: - // REQ sends request to A, A replies, B replies too. - // A's reply was first and matches, that is used. - // An hour later REQ sends a request to B. B's old reply is used. - msg_t drop; - while (true) { - rc = drop.init (); - errno_assert (rc == 0); - rc = dealer_t::xrecv (&drop); - if (rc != 0) - break; - drop.close (); - } - } - - bool more = msg_->flags () & msg_t::more ? true : false; - - int rc = dealer_t::xsend (msg_); - if (rc != 0) - return rc; - - // If the request was fully sent, flip the FSM into reply-receiving state. - if (!more) { - receiving_reply = true; - message_begins = true; - } - - return 0; -} - -int zmq::req_t::xrecv (msg_t *msg_) -{ - // If request wasn't send, we can't wait for reply. - if (!receiving_reply) { - errno = EFSM; - return -1; - } - - // Skip messages until one with the right first frames is found. - while (message_begins) { - // If enabled, the first frame must have the correct request_id. - if (request_id_frames_enabled) { - int rc = recv_reply_pipe (msg_); - if (rc != 0) - return rc; - - if (unlikely (!(msg_->flags () & msg_t::more) || - msg_->size () != sizeof (request_id) || - *static_cast<uint32_t *> (msg_->data ()) != request_id)) { - // Skip the remaining frames and try the next message - while (msg_->flags () & msg_t::more) { - rc = recv_reply_pipe (msg_); - errno_assert (rc == 0); - } - continue; - } - } - - // The next frame must be 0. - // TODO: Failing this check should also close the connection with the peer! - int rc = recv_reply_pipe (msg_); - if (rc != 0) - return rc; - - if (unlikely (!(msg_->flags () & msg_t::more) || msg_->size () != 0)) { - // Skip the remaining frames and try the next message - while (msg_->flags () & msg_t::more) { - rc = recv_reply_pipe (msg_); - errno_assert (rc == 0); - } - continue; - } - - message_begins = false; - } - - int rc = recv_reply_pipe (msg_); - if (rc != 0) - return rc; - - // If the reply is fully received, flip the FSM into request-sending state. - if (!(msg_->flags () & msg_t::more)) { - receiving_reply = false; - message_begins = true; - } - - return 0; -} - -bool zmq::req_t::xhas_in () -{ - // TODO: Duplicates should be removed here. - - if (!receiving_reply) - return false; - - return dealer_t::xhas_in (); -} - -bool zmq::req_t::xhas_out () -{ - if (receiving_reply) - return false; - - return dealer_t::xhas_out (); -} - -int zmq::req_t::xsetsockopt (int option_, const void *optval_, size_t optvallen_) -{ - bool is_int = (optvallen_ == sizeof (int)); - int value = is_int? *((int *) optval_): 0; - switch (option_) { - case ZMQ_REQ_CORRELATE: - if (is_int && value >= 0) { - request_id_frames_enabled = (value != 0); - return 0; - } - break; - - case ZMQ_REQ_RELAXED: - if (is_int && value >= 0) { - strict = (value == 0); - return 0; - } - break; - - default: - break; - } - - return dealer_t::xsetsockopt (option_, optval_, optvallen_); -} - -void zmq::req_t::xpipe_terminated (pipe_t *pipe_) -{ - if (reply_pipe == pipe_) - reply_pipe = NULL; - dealer_t::xpipe_terminated (pipe_); -} - -int zmq::req_t::recv_reply_pipe (msg_t *msg_) -{ - while (true) { - pipe_t *pipe = NULL; - int rc = dealer_t::recvpipe (msg_, &pipe); - if (rc != 0) - return rc; - if (!reply_pipe || pipe == reply_pipe) - return 0; - } -} - -zmq::req_session_t::req_session_t (io_thread_t *io_thread_, bool connect_, - socket_base_t *socket_, const options_t &options_, - const address_t *addr_) : - session_base_t (io_thread_, connect_, socket_, options_, addr_), - state (bottom) -{ -} - -zmq::req_session_t::~req_session_t () -{ -} - -int zmq::req_session_t::push_msg (msg_t *msg_) -{ - switch (state) { - case bottom: - if (msg_->flags () == msg_t::more && msg_->size () == 0) { - state = body; - return session_base_t::push_msg (msg_); - } - break; - case body: - if (msg_->flags () == msg_t::more) - return session_base_t::push_msg (msg_); - if (msg_->flags () == 0) { - state = bottom; - return session_base_t::push_msg (msg_); - } - break; - } - errno = EFAULT; - return -1; -} - -void zmq::req_session_t::reset () -{ - session_base_t::reset (); - state = bottom; -} diff --git a/src/req.hpp b/src/req.hpp deleted file mode 100644 index 6f079c3..0000000 --- a/src/req.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_REQ_HPP_INCLUDED__ -#define __ZMQ_REQ_HPP_INCLUDED__ - -#include "dealer.hpp" -#include "stdint.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class io_thread_t; - class socket_base_t; - - class req_t : public dealer_t - { - public: - - req_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~req_t (); - - // Overloads of functions from socket_base_t. - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - int xsetsockopt (int option_, const void *optval_, size_t optvallen_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - protected: - - // Receive only from the pipe the request was sent to, discarding - // frames from other pipes. - int recv_reply_pipe (zmq::msg_t *msg_); - - private: - - // If true, request was already sent and reply wasn't received yet or - // was raceived partially. - bool receiving_reply; - - // If true, we are starting to send/recv a message. The first part - // of the message must be empty message part (backtrace stack bottom). - bool message_begins; - - // The pipe the request was sent to and where the reply is expected. - zmq::pipe_t *reply_pipe; - - // Whether request id frames shall be sent and expected. - bool request_id_frames_enabled; - - // The current request id. It is incremented every time before a new - // request is sent. - uint32_t request_id; - - // If false, send() will reset its internal state and terminate the - // reply_pipe's connection instead of failing if a previous request is - // still pending. - bool strict; - - req_t (const req_t&); - const req_t &operator = (const req_t&); - }; - - class req_session_t : public session_base_t - { - public: - - req_session_t (zmq::io_thread_t *io_thread_, bool connect_, - zmq::socket_base_t *socket_, const options_t &options_, - const address_t *addr_); - ~req_session_t (); - - // Overloads of the functions from session_base_t. - int push_msg (msg_t *msg_); - void reset (); - - private: - - enum { - bottom, - body - } state; - - req_session_t (const req_session_t&); - const req_session_t &operator = (const req_session_t&); - }; - -} - -#endif diff --git a/src/router.cpp b/src/router.cpp deleted file mode 100644 index 6fabf67..0000000 --- a/src/router.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "router.hpp" -#include "pipe.hpp" -#include "wire.hpp" -#include "random.hpp" -#include "likely.hpp" -#include "err.hpp" - -zmq::router_t::router_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - prefetched (false), - identity_sent (false), - more_in (false), - current_out (NULL), - more_out (false), - next_peer_id (generate_random ()), - mandatory (false), - // raw_sock functionality in ROUTER is deprecated - raw_sock (false), - probe_router (false) -{ - options.type = ZMQ_ROUTER; - options.recv_identity = true; - options.raw_sock = false; - - prefetched_id.init (); - prefetched_msg.init (); -} - -zmq::router_t::~router_t () -{ - zmq_assert (anonymous_pipes.empty ());; - zmq_assert (outpipes.empty ()); - prefetched_id.close (); - prefetched_msg.close (); -} - -void zmq::router_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void)subscribe_to_all_; - - zmq_assert (pipe_); - - if (probe_router) { - msg_t probe_msg_; - int rc = probe_msg_.init (); - errno_assert (rc == 0); - - rc = pipe_->write (&probe_msg_); - // zmq_assert (rc) is not applicable here, since it is not a bug. - pipe_->flush (); - - rc = probe_msg_.close (); - errno_assert (rc == 0); - } - - bool identity_ok = identify_peer (pipe_); - if (identity_ok) - fq.attach (pipe_); - else - anonymous_pipes.insert (pipe_); -} - -int zmq::router_t::xsetsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - bool is_int = (optvallen_ == sizeof (int)); - int value = is_int? *((int *) optval_): 0; - - switch (option_) { - case ZMQ_ROUTER_RAW: - if (is_int && value >= 0) { - raw_sock = (value != 0); - if (raw_sock) { - options.recv_identity = false; - options.raw_sock = true; - } - return 0; - } - break; - - case ZMQ_ROUTER_MANDATORY: - if (is_int && value >= 0) { - mandatory = (value != 0); - return 0; - } - break; - - case ZMQ_PROBE_ROUTER: - if (is_int && value >= 0) { - probe_router = (value != 0); - return 0; - } - break; - - default: - break; - } - errno = EINVAL; - return -1; -} - - -void zmq::router_t::xpipe_terminated (pipe_t *pipe_) -{ - std::set <pipe_t*>::iterator it = anonymous_pipes.find (pipe_); - if (it != anonymous_pipes.end ()) - anonymous_pipes.erase (it); - else { - outpipes_t::iterator it = outpipes.find (pipe_->get_identity ()); - zmq_assert (it != outpipes.end ()); - outpipes.erase (it); - fq.pipe_terminated (pipe_); - if (pipe_ == current_out) - current_out = NULL; - } -} - -void zmq::router_t::xread_activated (pipe_t *pipe_) -{ - std::set <pipe_t*>::iterator it = anonymous_pipes.find (pipe_); - if (it == anonymous_pipes.end ()) - fq.activated (pipe_); - else { - bool identity_ok = identify_peer (pipe_); - if (identity_ok) { - anonymous_pipes.erase (it); - fq.attach (pipe_); - } - } -} - -void zmq::router_t::xwrite_activated (pipe_t *pipe_) -{ - outpipes_t::iterator it; - for (it = outpipes.begin (); it != outpipes.end (); ++it) - if (it->second.pipe == pipe_) - break; - - zmq_assert (it != outpipes.end ()); - zmq_assert (!it->second.active); - it->second.active = true; -} - -int zmq::router_t::xsend (msg_t *msg_) -{ - // If this is the first part of the message it's the ID of the - // peer to send the message to. - if (!more_out) { - zmq_assert (!current_out); - - // If we have malformed message (prefix with no subsequent message) - // then just silently ignore it. - // TODO: The connections should be killed instead. - if (msg_->flags () & msg_t::more) { - - more_out = true; - - // Find the pipe associated with the identity stored in the prefix. - // If there's no such pipe just silently ignore the message, unless - // router_mandatory is set. - blob_t identity ((unsigned char*) msg_->data (), msg_->size ()); - outpipes_t::iterator it = outpipes.find (identity); - - if (it != outpipes.end ()) { - current_out = it->second.pipe; - if (!current_out->check_write ()) { - it->second.active = false; - current_out = NULL; - if (mandatory) { - more_out = false; - errno = EAGAIN; - return -1; - } - } - } - else - if (mandatory) { - more_out = false; - errno = EHOSTUNREACH; - return -1; - } - } - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - return 0; - } - - // Ignore the MORE flag for raw-sock or assert? - if (options.raw_sock) - msg_->reset_flags (msg_t::more); - - // Check whether this is the last part of the message. - more_out = msg_->flags () & msg_t::more ? true : false; - - // Push the message into the pipe. If there's no out pipe, just drop it. - if (current_out) { - - // 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 (raw_sock && msg_->size() == 0) { - current_out->terminate (false); - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - current_out = NULL; - return 0; - } - - bool ok = current_out->write (msg_); - if (unlikely (!ok)) - current_out = NULL; - else - if (!more_out) { - current_out->flush (); - current_out = NULL; - } - } - else { - int rc = msg_->close (); - errno_assert (rc == 0); - } - - // Detach the message from the data buffer. - int rc = msg_->init (); - errno_assert (rc == 0); - - return 0; -} - -int zmq::router_t::xrecv (msg_t *msg_) -{ - if (prefetched) { - if (!identity_sent) { - int rc = msg_->move (prefetched_id); - errno_assert (rc == 0); - identity_sent = true; - } - else { - int rc = msg_->move (prefetched_msg); - errno_assert (rc == 0); - prefetched = false; - } - more_in = msg_->flags () & msg_t::more ? true : false; - return 0; - } - - pipe_t *pipe = NULL; - int rc = fq.recvpipe (msg_, &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. - while (rc == 0 && msg_->is_identity ()) - rc = fq.recvpipe (msg_, &pipe); - - if (rc != 0) - return -1; - - zmq_assert (pipe != NULL); - - // If we are in the middle of reading a message, just return the next part. - if (more_in) - more_in = msg_->flags () & msg_t::more ? true : false; - 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. - rc = prefetched_msg.move (*msg_); - errno_assert (rc == 0); - prefetched = true; - - blob_t identity = pipe->get_identity (); - rc = msg_->init_size (identity.size ()); - errno_assert (rc == 0); - memcpy (msg_->data (), identity.data (), identity.size ()); - msg_->set_flags (msg_t::more); - identity_sent = true; - } - - return 0; -} - -int zmq::router_t::rollback (void) -{ - if (current_out) { - current_out->rollback (); - current_out = NULL; - more_out = false; - } - return 0; -} - -bool zmq::router_t::xhas_in () -{ - // If we are in the middle of reading the messages, there are - // definitely more parts available. - if (more_in) - return true; - - // We may already have a message pre-fetched. - if (prefetched) - return true; - - // Try to read the next message. - // The message, if read, is kept in the pre-fetch buffer. - pipe_t *pipe = NULL; - int rc = fq.recvpipe (&prefetched_msg, &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 (rc == 0 && prefetched_msg.is_identity ()) - rc = fq.recvpipe (&prefetched_msg, &pipe); - - if (rc != 0) - return false; - - zmq_assert (pipe != NULL); - - blob_t identity = pipe->get_identity (); - rc = prefetched_id.init_size (identity.size ()); - errno_assert (rc == 0); - memcpy (prefetched_id.data (), identity.data (), identity.size ()); - prefetched_id.set_flags (msg_t::more); - - prefetched = true; - identity_sent = false; - - return true; -} - -bool zmq::router_t::xhas_out () -{ - // In theory, ROUTER socket is always ready for writing. Whether actual - // attempt to write succeeds depends on whitch pipe the message is going - // to be routed to. - return true; -} - -bool zmq::router_t::identify_peer (pipe_t *pipe_) -{ - msg_t msg; - blob_t identity; - bool ok; - - if (options.raw_sock) { // Always assign identity for raw-socket - unsigned char buf [5]; - buf [0] = 0; - put_uint32 (buf + 1, next_peer_id++); - identity = blob_t (buf, sizeof buf); - } - else { - msg.init (); - ok = pipe_->read (&msg); - if (!ok) - return false; - - if (msg.size () == 0) { - // Fall back on the auto-generation - unsigned char buf [5]; - buf [0] = 0; - put_uint32 (buf + 1, next_peer_id++); - identity = blob_t (buf, sizeof buf); - msg.close (); - } - else { - identity = blob_t ((unsigned char*) msg.data (), msg.size ()); - outpipes_t::iterator it = outpipes.find (identity); - msg.close (); - - // Ignore peers with duplicate ID. - if (it != outpipes.end ()) - return false; - } - } - - pipe_->set_identity (identity); - // Add the record into output pipes lookup table - outpipe_t outpipe = {pipe_, true}; - ok = outpipes.insert (outpipes_t::value_type (identity, outpipe)).second; - zmq_assert (ok); - - return true; -} diff --git a/src/router.hpp b/src/router.hpp deleted file mode 100644 index 7b29708..0000000 --- a/src/router.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_ROUTER_HPP_INCLUDED__ -#define __ZMQ_ROUTER_HPP_INCLUDED__ - -#include <map> - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "stdint.hpp" -#include "blob.hpp" -#include "msg.hpp" -#include "fq.hpp" - -namespace zmq -{ - - class ctx_t; - class pipe_t; - - // TODO: This class uses O(n) scheduling. Rewrite it to use O(1) algorithm. - class router_t : - public socket_base_t - { - public: - - router_t (zmq::ctx_t *parent_, uint32_t tid_, int sid); - ~router_t (); - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsetsockopt (int option_, const void *optval_, size_t optvallen_); - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - protected: - - // Rollback any message parts that were sent but not yet flushed. - int rollback (); - - private: - - // Receive peer id and update lookup map - bool identify_peer (pipe_t *pipe_); - - // Fair queueing object for inbound pipes. - fq_t fq; - - // True iff there is a message held in the pre-fetch buffer. - bool prefetched; - - // If true, the receiver got the message part with - // the peer's identity. - bool identity_sent; - - // Holds the prefetched identity. - msg_t prefetched_id; - - // Holds the prefetched message. - msg_t prefetched_msg; - - // If true, more incoming message parts are expected. - bool more_in; - - struct outpipe_t - { - zmq::pipe_t *pipe; - bool active; - }; - - // We keep a set of pipes that have not been identified yet. - std::set <pipe_t*> anonymous_pipes; - - // Outbound pipes indexed by the peer IDs. - typedef std::map <blob_t, outpipe_t> outpipes_t; - outpipes_t outpipes; - - // The pipe we are currently writing to. - zmq::pipe_t *current_out; - - // If true, more outgoing message parts are expected. - bool more_out; - - // Peer ID are generated. It's a simple increment and wrap-over - // algorithm. This value is the next ID to use (if not used already). - uint32_t next_peer_id; - - // If true, report EAGAIN to the caller instead of silently dropping - // the message targeting an unknown peer. - bool mandatory; - bool raw_sock; - - // if true, send an empty message to every connected router peer - bool probe_router; - - router_t (const router_t&); - const router_t &operator = (const router_t&); - }; - -} - -#endif diff --git a/src/select.cpp b/src/select.cpp deleted file mode 100644 index b5cb972..0000000 --- a/src/select.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "select.hpp" -#if defined ZMQ_USE_SELECT - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#elif defined ZMQ_HAVE_HPUX -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> -#elif defined ZMQ_HAVE_OPENVMS -#include <sys/types.h> -#include <sys/time.h> -#else -#include <sys/select.h> -#endif - -#include <string.h> -#include <algorithm> - -#include "err.hpp" -#include "config.hpp" -#include "i_poll_events.hpp" - -zmq::select_t::select_t () : - maxfd (retired_fd), - retired (false), - stopping (false) -{ - // Clear file descriptor sets. - FD_ZERO (&source_set_in); - FD_ZERO (&source_set_out); - FD_ZERO (&source_set_err); -} - -zmq::select_t::~select_t () -{ - worker.stop (); -} - -zmq::select_t::handle_t zmq::select_t::add_fd (fd_t fd_, i_poll_events *events_) -{ - // Store the file descriptor. - fd_entry_t entry = {fd_, events_}; - fds.push_back (entry); - - // Ensure we do not attempt to select () on more than FD_SETSIZE - // file descriptors. - zmq_assert (fds.size () <= FD_SETSIZE); - - // Start polling on errors. - FD_SET (fd_, &source_set_err); - - // Adjust maxfd if necessary. - if (fd_ > maxfd) - maxfd = fd_; - - // Increase the load metric of the thread. - adjust_load (1); - - return fd_; -} - -void zmq::select_t::rm_fd (handle_t handle_) -{ - // Mark the descriptor as retired. - fd_set_t::iterator it; - for (it = fds.begin (); it != fds.end (); ++it) - if (it->fd == handle_) - break; - zmq_assert (it != fds.end ()); - it->fd = retired_fd; - retired = true; - - // Stop polling on the descriptor. - FD_CLR (handle_, &source_set_in); - FD_CLR (handle_, &source_set_out); - FD_CLR (handle_, &source_set_err); - - // Discard all events generated on this file descriptor. - FD_CLR (handle_, &readfds); - FD_CLR (handle_, &writefds); - FD_CLR (handle_, &exceptfds); - - // Adjust the maxfd attribute if we have removed the - // highest-numbered file descriptor. - if (handle_ == maxfd) { - maxfd = retired_fd; - for (fd_set_t::iterator it = fds.begin (); it != fds.end (); ++it) - if (it->fd > maxfd) - maxfd = it->fd; - } - - // Decrease the load metric of the thread. - adjust_load (-1); -} - -void zmq::select_t::set_pollin (handle_t handle_) -{ - FD_SET (handle_, &source_set_in); -} - -void zmq::select_t::reset_pollin (handle_t handle_) -{ - FD_CLR (handle_, &source_set_in); -} - -void zmq::select_t::set_pollout (handle_t handle_) -{ - FD_SET (handle_, &source_set_out); -} - -void zmq::select_t::reset_pollout (handle_t handle_) -{ - FD_CLR (handle_, &source_set_out); -} - -void zmq::select_t::start () -{ - worker.start (worker_routine, this); -} - -void zmq::select_t::stop () -{ - stopping = true; -} - -int zmq::select_t::max_fds () -{ - return FD_SETSIZE; -} - -void zmq::select_t::loop () -{ - while (!stopping) { - - // Execute any due timers. - int timeout = (int) execute_timers (); - - // Intialise the pollsets. - memcpy (&readfds, &source_set_in, sizeof source_set_in); - memcpy (&writefds, &source_set_out, sizeof source_set_out); - memcpy (&exceptfds, &source_set_err, sizeof source_set_err); - - // Wait for events. - struct timeval tv = {(long) (timeout / 1000), - (long) (timeout % 1000 * 1000)}; -#ifdef ZMQ_HAVE_WINDOWS - int rc = select (0, &readfds, &writefds, &exceptfds, - timeout ? &tv : NULL); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = select (maxfd + 1, &readfds, &writefds, &exceptfds, - timeout ? &tv : NULL); - if (rc == -1) { - errno_assert (errno == EINTR); - continue; - } -#endif - - // If there are no events (i.e. it's a timeout) there's no point - // in checking the pollset. - if (rc == 0) - continue; - - for (fd_set_t::size_type i = 0; i < fds.size (); i ++) { - if (fds [i].fd == retired_fd) - continue; - if (FD_ISSET (fds [i].fd, &exceptfds)) - fds [i].events->in_event (); - if (fds [i].fd == retired_fd) - continue; - if (FD_ISSET (fds [i].fd, &writefds)) - fds [i].events->out_event (); - if (fds [i].fd == retired_fd) - continue; - if (FD_ISSET (fds [i].fd, &readfds)) - fds [i].events->in_event (); - } - - // Destroy retired event sources. - if (retired) { - fds.erase (std::remove_if (fds.begin (), fds.end (), - zmq::select_t::is_retired_fd), fds.end ()); - retired = false; - } - } -} - -void zmq::select_t::worker_routine (void *arg_) -{ - ((select_t*) arg_)->loop (); -} - -bool zmq::select_t::is_retired_fd (const fd_entry_t &entry) -{ - return (entry.fd == retired_fd); -} - -#endif diff --git a/src/select.hpp b/src/select.hpp deleted file mode 100644 index 9c3ef47..0000000 --- a/src/select.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_SELECT_HPP_INCLUDED__ -#define __ZMQ_SELECT_HPP_INCLUDED__ - -// poller.hpp decides which polling mechanism to use. -#include "poller.hpp" -#if defined ZMQ_USE_SELECT - -#include "platform.hpp" - -#include <stddef.h> -#include <vector> - -#ifdef ZMQ_HAVE_WINDOWS -#include "winsock2.h" -#elif defined ZMQ_HAVE_OPENVMS -#include <sys/types.h> -#include <sys/time.h> -#else -#include <sys/select.h> -#endif - -#include "fd.hpp" -#include "thread.hpp" -#include "poller_base.hpp" - -namespace zmq -{ - - struct i_poll_events; - - // Implements socket polling mechanism using POSIX.1-2001 select() - // function. - - class select_t : public poller_base_t - { - public: - - typedef fd_t handle_t; - - select_t (); - ~select_t (); - - // "poller" concept. - handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); - void rm_fd (handle_t handle_); - void set_pollin (handle_t handle_); - void reset_pollin (handle_t handle_); - void set_pollout (handle_t handle_); - void reset_pollout (handle_t handle_); - void start (); - void stop (); - - static int max_fds (); - - private: - - // Main worker thread routine. - static void worker_routine (void *arg_); - - // Main event loop. - void loop (); - - struct fd_entry_t - { - fd_t fd; - zmq::i_poll_events *events; - }; - - // Checks if an fd_entry_t is retired. - static bool is_retired_fd (const fd_entry_t &entry); - - // Set of file descriptors that are used to retreive - // information for fd_set. - typedef std::vector <fd_entry_t> fd_set_t; - fd_set_t fds; - - fd_set source_set_in; - fd_set source_set_out; - fd_set source_set_err; - - fd_set readfds; - fd_set writefds; - fd_set exceptfds; - - // Maximum file descriptor. - fd_t maxfd; - - // If true, at least one file descriptor has retired. - bool retired; - - // If true, thread is shutting down. - bool stopping; - - // Handle of the physical thread doing the I/O work. - thread_t worker; - - select_t (const select_t&); - const select_t &operator = (const select_t&); - }; - - typedef select_t poller_t; - -} - -#endif - -#endif diff --git a/src/session_base.cpp b/src/session_base.cpp deleted file mode 100644 index 7e27e31..0000000 --- a/src/session_base.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "session_base.hpp" -#include "i_engine.hpp" -#include "err.hpp" -#include "pipe.hpp" -#include "likely.hpp" -#include "tcp_connecter.hpp" -#include "ipc_connecter.hpp" -#include "pgm_sender.hpp" -#include "pgm_receiver.hpp" -#include "address.hpp" - -#include "ctx.hpp" -#include "req.hpp" - -zmq::session_base_t *zmq::session_base_t::create (class io_thread_t *io_thread_, - bool connect_, class socket_base_t *socket_, const options_t &options_, - const address_t *addr_) -{ - session_base_t *s = NULL; - switch (options_.type) { - case ZMQ_REQ: - s = new (std::nothrow) req_session_t (io_thread_, connect_, - socket_, options_, addr_); - break; - case ZMQ_DEALER: - case ZMQ_REP: - case ZMQ_ROUTER: - case ZMQ_PUB: - case ZMQ_XPUB: - case ZMQ_SUB: - case ZMQ_XSUB: - case ZMQ_PUSH: - case ZMQ_PULL: - case ZMQ_PAIR: - case ZMQ_STREAM: - s = new (std::nothrow) session_base_t (io_thread_, connect_, - socket_, options_, addr_); - break; - default: - errno = EINVAL; - return NULL; - } - alloc_assert (s); - return s; -} - -zmq::session_base_t::session_base_t (class io_thread_t *io_thread_, - bool connect_, class socket_base_t *socket_, const options_t &options_, - const address_t *addr_) : - own_t (io_thread_, options_), - io_object_t (io_thread_), - connect (connect_), - pipe (NULL), - zap_pipe (NULL), - incomplete_in (false), - pending (false), - engine (NULL), - socket (socket_), - io_thread (io_thread_), - has_linger_timer (false), - addr (addr_) -{ -} - -zmq::session_base_t::~session_base_t () -{ - zmq_assert (!pipe); - zmq_assert (!zap_pipe); - - // If there's still a pending linger timer, remove it. - if (has_linger_timer) { - cancel_timer (linger_timer_id); - has_linger_timer = false; - } - - // Close the engine. - if (engine) - engine->terminate (); - - delete addr; -} - -void zmq::session_base_t::attach_pipe (pipe_t *pipe_) -{ - zmq_assert (!is_terminating ()); - zmq_assert (!pipe); - zmq_assert (pipe_); - pipe = pipe_; - pipe->set_event_sink (this); -} - -int zmq::session_base_t::pull_msg (msg_t *msg_) -{ - if (!pipe || !pipe->read (msg_)) { - errno = EAGAIN; - return -1; - } - incomplete_in = msg_->flags () & msg_t::more ? true : false; - - return 0; -} - -int zmq::session_base_t::push_msg (msg_t *msg_) -{ - if (pipe && pipe->write (msg_)) { - int rc = msg_->init (); - errno_assert (rc == 0); - return 0; - } - - errno = EAGAIN; - return -1; -} - -int zmq::session_base_t::read_zap_msg (msg_t *msg_) -{ - if (zap_pipe == NULL) { - errno = ENOTCONN; - return -1; - } - - if (!zap_pipe->read (msg_)) { - errno = EAGAIN; - return -1; - } - - return 0; -} - -int zmq::session_base_t::write_zap_msg (msg_t *msg_) -{ - if (zap_pipe == NULL) { - errno = ENOTCONN; - return -1; - } - - const bool ok = zap_pipe->write (msg_); - zmq_assert (ok); - - if ((msg_->flags () & msg_t::more) == 0) - zap_pipe->flush (); - - const int rc = msg_->init (); - errno_assert (rc == 0); - return 0; -} - -void zmq::session_base_t::reset () -{ -} - -void zmq::session_base_t::flush () -{ - if (pipe) - pipe->flush (); -} - -void zmq::session_base_t::clean_pipes () -{ - if (pipe) { - - // Get rid of half-processed messages in the out pipe. Flush any - // unflushed messages upstream. - pipe->rollback (); - pipe->flush (); - - // Remove any half-read message from the in pipe. - while (incomplete_in) { - msg_t msg; - int rc = msg.init (); - errno_assert (rc == 0); - rc = pull_msg (&msg); - errno_assert (rc == 0); - rc = msg.close (); - errno_assert (rc == 0); - } - } -} - -void zmq::session_base_t::pipe_terminated (pipe_t *pipe_) -{ - // Drop the reference to the deallocated pipe if required. - zmq_assert (pipe_ == pipe - || pipe_ == zap_pipe - || terminating_pipes.count (pipe_) == 1); - - if (pipe_ == pipe) - // If this is our current pipe, remove it - pipe = NULL; - else - if (pipe_ == zap_pipe) { - zap_pipe = NULL; - } - else - // Remove the pipe from the detached pipes set - terminating_pipes.erase (pipe_); - - if (!is_terminating () && options.raw_sock) { - if (engine) { - engine->terminate (); - engine = NULL; - } - terminate (); - } - - // If we are waiting for pending messages to be sent, at this point - // we are sure that there will be no more messages and we can proceed - // with termination safely. - if (pending && !pipe && !zap_pipe && terminating_pipes.empty ()) - proceed_with_term (); -} - -void zmq::session_base_t::read_activated (pipe_t *pipe_) -{ - // Skip activating if we're detaching this pipe - if (unlikely(pipe_ != pipe && pipe_ != zap_pipe)) { - zmq_assert (terminating_pipes.count (pipe_) == 1); - return; - } - - if (unlikely (engine == NULL)) { - pipe->check_read (); - return; - } - - if (likely (pipe_ == pipe)) - engine->restart_output (); - else - engine->zap_msg_available (); -} - -void zmq::session_base_t::write_activated (pipe_t *pipe_) -{ - // Skip activating if we're detaching this pipe - if (pipe != pipe_) { - zmq_assert (terminating_pipes.count (pipe_) == 1); - return; - } - - if (engine) - engine->restart_input (); -} - -void zmq::session_base_t::hiccuped (pipe_t *) -{ - // Hiccups are always sent from session to socket, not the other - // way round. - zmq_assert (false); -} - -zmq::socket_base_t *zmq::session_base_t::get_socket () -{ - return socket; -} - -void zmq::session_base_t::process_plug () -{ - if (connect) - start_connecting (false); -} - -int zmq::session_base_t::zap_connect () -{ - zmq_assert (zap_pipe == NULL); - - endpoint_t peer = find_endpoint ("inproc://zeromq.zap.01"); - if (peer.socket == NULL) { - errno = ECONNREFUSED; - return -1; - } - if (peer.options.type != ZMQ_REP - && peer.options.type != ZMQ_ROUTER) { - errno = ECONNREFUSED; - return -1; - } - - // Create a bi-directional pipe that will connect - // session with zap socket. - object_t *parents [2] = {this, peer.socket}; - pipe_t *new_pipes [2] = {NULL, NULL}; - int hwms [2] = {0, 0}; - bool conflates [2] = {false, false}; - int rc = pipepair (parents, new_pipes, hwms, conflates); - errno_assert (rc == 0); - - // Attach local end of the pipe to this socket object. - zap_pipe = new_pipes [0]; - zap_pipe->set_nodelay (); - zap_pipe->set_event_sink (this); - - new_pipes [1]->set_nodelay (); - send_bind (peer.socket, new_pipes [1], false); - - // Send empty identity if required by the peer. - if (peer.options.recv_identity) { - msg_t id; - rc = id.init (); - errno_assert (rc == 0); - id.set_flags (msg_t::identity); - bool ok = zap_pipe->write (&id); - zmq_assert (ok); - zap_pipe->flush (); - } - - return 0; -} - -void zmq::session_base_t::process_attach (i_engine *engine_) -{ - zmq_assert (engine_ != NULL); - - // Create the pipe if it does not exist yet. - if (!pipe && !is_terminating ()) { - object_t *parents [2] = {this, socket}; - pipe_t *pipes [2] = {NULL, NULL}; - - bool conflate = options.conflate && - (options.type == ZMQ_DEALER || - options.type == ZMQ_PULL || - options.type == ZMQ_PUSH || - options.type == ZMQ_PUB || - options.type == ZMQ_SUB); - - int hwms [2] = {conflate? -1 : options.rcvhwm, - conflate? -1 : options.sndhwm}; - bool conflates [2] = {conflate, conflate}; - int rc = pipepair (parents, pipes, hwms, conflates); - errno_assert (rc == 0); - - // Plug the local end of the pipe. - pipes [0]->set_event_sink (this); - - // Remember the local end of the pipe. - zmq_assert (!pipe); - pipe = pipes [0]; - - // Ask socket to plug into the remote end of the pipe. - send_bind (socket, pipes [1]); - } - - // Plug in the engine. - zmq_assert (!engine); - engine = engine_; - engine->plug (io_thread, this); -} - -void zmq::session_base_t::detach () -{ - // Engine is dead. Let's forget about it. - engine = NULL; - - // Remove any half-done messages from the pipes. - clean_pipes (); - - // Send the event to the derived class. - detached (); - - // Just in case there's only a delimiter in the pipe. - if (pipe) - pipe->check_read (); - - if (zap_pipe) - zap_pipe->check_read (); -} - -void zmq::session_base_t::process_term (int linger_) -{ - zmq_assert (!pending); - - // If the termination of the pipe happens before the term command is - // delivered there's nothing much to do. We can proceed with the - // standard termination immediately. - if (!pipe && !zap_pipe) { - proceed_with_term (); - return; - } - - pending = true; - - if (pipe != NULL) { - // If there's finite linger value, delay the termination. - // If linger is infinite (negative) we don't even have to set - // the timer. - if (linger_ > 0) { - zmq_assert (!has_linger_timer); - add_timer (linger_, linger_timer_id); - has_linger_timer = true; - } - - // Start pipe termination process. Delay the termination till all messages - // are processed in case the linger time is non-zero. - pipe->terminate (linger_ != 0); - - // TODO: Should this go into pipe_t::terminate ? - // In case there's no engine and there's only delimiter in the - // pipe it wouldn't be ever read. Thus we check for it explicitly. - pipe->check_read (); - } - - if (zap_pipe != NULL) - zap_pipe->terminate (false); -} - -void zmq::session_base_t::proceed_with_term () -{ - // The pending phase has just ended. - pending = false; - - // Continue with standard termination. - own_t::process_term (0); -} - -void zmq::session_base_t::timer_event (int id_) -{ - - // Linger period expired. We can proceed with termination even though - // there are still pending messages to be sent. - zmq_assert (id_ == linger_timer_id); - has_linger_timer = false; - - // Ask pipe to terminate even though there may be pending messages in it. - zmq_assert (pipe); - pipe->terminate (false); -} - -void zmq::session_base_t::detached () -{ - // Transient session self-destructs after peer disconnects. - if (!connect) { - terminate (); - return; - } - - // For delayed connect situations, terminate the pipe - // and reestablish later on - if (pipe && options.immediate == 1 - && addr->protocol != "pgm" && addr->protocol != "epgm") { - pipe->hiccup (); - pipe->terminate (false); - terminating_pipes.insert (pipe); - pipe = NULL; - } - - reset (); - - // Reconnect. - if (options.reconnect_ivl != -1) - start_connecting (true); - - // For subscriber sockets we hiccup the inbound pipe, which will cause - // the socket object to resend all the subscriptions. - if (pipe && (options.type == ZMQ_SUB || options.type == ZMQ_XSUB)) - pipe->hiccup (); -} - -void zmq::session_base_t::start_connecting (bool wait_) -{ - zmq_assert (connect); - - // Choose I/O thread to run connecter in. Given that we are already - // running in an I/O thread, there must be at least one available. - io_thread_t *io_thread = choose_io_thread (options.affinity); - zmq_assert (io_thread); - - // Create the connecter object. - - if (addr->protocol == "tcp") { - tcp_connecter_t *connecter = new (std::nothrow) tcp_connecter_t ( - io_thread, this, options, addr, wait_); - alloc_assert (connecter); - launch_child (connecter); - return; - } - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - if (addr->protocol == "ipc") { - ipc_connecter_t *connecter = new (std::nothrow) ipc_connecter_t ( - io_thread, this, options, addr, wait_); - alloc_assert (connecter); - launch_child (connecter); - return; - } -#endif - -#ifdef ZMQ_HAVE_OPENPGM - - // Both PGM and EPGM transports are using the same infrastructure. - if (addr->protocol == "pgm" || addr->protocol == "epgm") { - - zmq_assert (options.type == ZMQ_PUB || options.type == ZMQ_XPUB - || options.type == ZMQ_SUB || options.type == ZMQ_XSUB); - - // For EPGM transport with UDP encapsulation of PGM is used. - bool const udp_encapsulation = addr->protocol == "epgm"; - - // At this point we'll create message pipes to the session straight - // away. There's no point in delaying it as no concept of 'connect' - // exists with PGM anyway. - if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB) { - - // PGM sender. - pgm_sender_t *pgm_sender = new (std::nothrow) pgm_sender_t ( - io_thread, options); - alloc_assert (pgm_sender); - - int rc = pgm_sender->init (udp_encapsulation, addr->address.c_str ()); - errno_assert (rc == 0); - - send_attach (this, pgm_sender); - } - else { - - // PGM receiver. - pgm_receiver_t *pgm_receiver = new (std::nothrow) pgm_receiver_t ( - io_thread, options); - alloc_assert (pgm_receiver); - - int rc = pgm_receiver->init (udp_encapsulation, addr->address.c_str ()); - errno_assert (rc == 0); - - send_attach (this, pgm_receiver); - } - - return; - } -#endif - - zmq_assert (false); -} - diff --git a/src/session_base.hpp b/src/session_base.hpp deleted file mode 100644 index 2ef7dc5..0000000 --- a/src/session_base.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_SESSION_BASE_HPP_INCLUDED__ -#define __ZMQ_SESSION_BASE_HPP_INCLUDED__ - -#include <string> -#include <stdarg.h> - -#include "own.hpp" -#include "io_object.hpp" -#include "pipe.hpp" -#include "socket_base.hpp" - -namespace zmq -{ - - class pipe_t; - class io_thread_t; - class socket_base_t; - struct i_engine; - struct address_t; - - class session_base_t : - public own_t, - public io_object_t, - public i_pipe_events - { - public: - - // Create a session of the particular type. - static session_base_t *create (zmq::io_thread_t *io_thread_, - bool connect_, zmq::socket_base_t *socket_, - const options_t &options_, const address_t *addr_); - - // To be used once only, when creating the session. - void attach_pipe (zmq::pipe_t *pipe_); - - // Following functions are the interface exposed towards the engine. - virtual void reset (); - void flush (); - void detach (); - - // i_pipe_events interface implementation. - void read_activated (zmq::pipe_t *pipe_); - void write_activated (zmq::pipe_t *pipe_); - void hiccuped (zmq::pipe_t *pipe_); - void pipe_terminated (zmq::pipe_t *pipe_); - - // Delivers a message. Returns 0 if successful; -1 otherwise. - // The function takes ownership of the message. - int push_msg (msg_t *msg_); - - int zap_connect (); - - // Fetches a message. Returns 0 if successful; -1 otherwise. - // The caller is responsible for freeing the message when no - // longer used. - int pull_msg (msg_t *msg_); - - // Receives message from ZAP socket. - // Returns 0 on success; -1 otherwise. - // The caller is responsible for freeing the message. - int read_zap_msg (msg_t *msg_); - - // Sends message to ZAP socket. - // Returns 0 on success; -1 otherwise. - // The function takes ownership of the message. - int write_zap_msg (msg_t *msg_); - - socket_base_t *get_socket (); - - protected: - - session_base_t (zmq::io_thread_t *io_thread_, bool connect_, - zmq::socket_base_t *socket_, const options_t &options_, - const address_t *addr_); - virtual ~session_base_t (); - - private: - - void start_connecting (bool wait_); - - void detached (); - - // Handlers for incoming commands. - void process_plug (); - void process_attach (zmq::i_engine *engine_); - void process_term (int linger_); - - // i_poll_events handlers. - void timer_event (int id_); - - // Remove any half processed messages. Flush unflushed messages. - // Call this function when engine disconnect to get rid of leftovers. - void clean_pipes (); - - // Call this function to move on with the delayed process_term. - void proceed_with_term (); - - // If true, this session (re)connects to the peer. Otherwise, it's - // a transient session created by the listener. - bool connect; - - // Pipe connecting the session to its socket. - zmq::pipe_t *pipe; - - // Pipe used to exchange messages with ZAP socket. - zmq::pipe_t *zap_pipe; - - // This set is added to with pipes we are disconnecting, but haven't yet completed - std::set <pipe_t *> terminating_pipes; - - // This flag is true if the remainder of the message being processed - // is still in the in pipe. - bool incomplete_in; - - // True if termination have been suspended to push the pending - // messages to the network. - bool pending; - - // The protocol I/O engine connected to the session. - zmq::i_engine *engine; - - // The socket the session belongs to. - zmq::socket_base_t *socket; - - // I/O thread the session is living in. It will be used to plug in - // the engines into the same thread. - zmq::io_thread_t *io_thread; - - // ID of the linger timer - enum {linger_timer_id = 0x20}; - - // True is linger timer is running. - bool has_linger_timer; - - // Protocol and address to use when connecting. - const address_t *addr; - - session_base_t (const session_base_t&); - const session_base_t &operator = (const session_base_t&); - }; - -} - -#endif diff --git a/src/signaler.cpp b/src/signaler.cpp deleted file mode 100644 index 3fb3632..0000000 --- a/src/signaler.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#if defined ZMQ_FORCE_SELECT -#define ZMQ_SIGNALER_WAIT_BASED_ON_SELECT -#elif defined ZMQ_FORCE_POLL -#define ZMQ_SIGNALER_WAIT_BASED_ON_POLL -#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\ - defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\ - defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\ - defined ZMQ_HAVE_NETBSD -#define ZMQ_SIGNALER_WAIT_BASED_ON_POLL -#elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS ||\ - defined ZMQ_HAVE_CYGWIN -#define ZMQ_SIGNALER_WAIT_BASED_ON_SELECT -#endif - -// On AIX, poll.h has to be included before zmq.h to get consistent -// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents' -// instead of 'events' and 'revents' and defines macros to map from POSIX-y -// names to AIX-specific names). -#if defined ZMQ_SIGNALER_WAIT_BASED_ON_POLL -#include <poll.h> -#elif defined ZMQ_SIGNALER_WAIT_BASED_ON_SELECT -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#elif defined ZMQ_HAVE_HPUX -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> -#elif defined ZMQ_HAVE_OPENVMS -#include <sys/types.h> -#include <sys/time.h> -#else -#include <sys/select.h> -#endif -#endif - -#include "signaler.hpp" -#include "likely.hpp" -#include "stdint.hpp" -#include "config.hpp" -#include "err.hpp" -#include "fd.hpp" -#include "ip.hpp" - -#if defined ZMQ_HAVE_EVENTFD -#include <sys/eventfd.h> -#endif - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#include <netinet/tcp.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#endif - -zmq::signaler_t::signaler_t () -{ - // Create the socketpair for signaling. - if (make_fdpair (&r, &w) == 0) { - unblock_socket (w); - unblock_socket (r); - } -#ifdef HAVE_FORK - pid = getpid(); -#endif -} - -zmq::signaler_t::~signaler_t () -{ -#if defined ZMQ_HAVE_EVENTFD - int rc = close (r); - errno_assert (rc == 0); -#elif defined ZMQ_HAVE_WINDOWS - struct linger so_linger = { 1, 0 }; - int rc = setsockopt (w, SOL_SOCKET, SO_LINGER, - (char *)&so_linger, sizeof (so_linger)); - wsa_assert (rc != SOCKET_ERROR); - rc = closesocket (w); - wsa_assert (rc != SOCKET_ERROR); - rc = closesocket (r); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = close (w); - errno_assert (rc == 0); - rc = close (r); - errno_assert (rc == 0); -#endif -} - -zmq::fd_t zmq::signaler_t::get_fd () -{ - return r; -} - -void zmq::signaler_t::send () -{ -#if HAVE_FORK - if (unlikely(pid != getpid())) { - //printf("Child process %d signaler_t::send returning without sending #1\n", getpid()); - return; // do not send anything in forked child context - } -#endif -#if defined ZMQ_HAVE_EVENTFD - const uint64_t inc = 1; - ssize_t sz = write (w, &inc, sizeof (inc)); - errno_assert (sz == sizeof (inc)); -#elif defined ZMQ_HAVE_WINDOWS - unsigned char dummy = 0; - int nbytes = ::send (w, (char*) &dummy, sizeof (dummy), 0); - wsa_assert (nbytes != SOCKET_ERROR); - zmq_assert (nbytes == sizeof (dummy)); -#else - unsigned char dummy = 0; - while (true) { - ssize_t nbytes = ::send (w, &dummy, sizeof (dummy), 0); - if (unlikely (nbytes == -1 && errno == EINTR)) - continue; -#if HAVE_FORK - if (unlikely(pid != getpid())) { - //printf("Child process %d signaler_t::send returning without sending #2\n", getpid()); - errno = EINTR; - break; - } -#endif - zmq_assert (nbytes == sizeof (dummy)); - break; - } -#endif -} - -int zmq::signaler_t::wait (int timeout_) -{ -#ifdef HAVE_FORK - if (unlikely(pid != getpid())) - { - // we have forked and the file descriptor is closed. Emulate an interupt - // response. - //printf("Child process %d signaler_t::wait returning simulating interrupt #1\n", getpid()); - errno = EINTR; - return -1; - } -#endif - -#ifdef ZMQ_SIGNALER_WAIT_BASED_ON_POLL - - struct pollfd pfd; - pfd.fd = r; - pfd.events = POLLIN; - int rc = poll (&pfd, 1, timeout_); - if (unlikely (rc < 0)) { - errno_assert (errno == EINTR); - return -1; - } - else - if (unlikely (rc == 0)) { - errno = EAGAIN; - return -1; - } -#ifdef HAVE_FORK - if (unlikely(pid != getpid())) { - // we have forked and the file descriptor is closed. Emulate an interupt - // response. - //printf("Child process %d signaler_t::wait returning simulating interrupt #2\n", getpid()); - errno = EINTR; - return -1; - } -#endif - zmq_assert (rc == 1); - zmq_assert (pfd.revents & POLLIN); - return 0; - -#elif defined ZMQ_SIGNALER_WAIT_BASED_ON_SELECT - - fd_set fds; - FD_ZERO (&fds); - FD_SET (r, &fds); - struct timeval timeout; - if (timeout_ >= 0) { - timeout.tv_sec = timeout_ / 1000; - timeout.tv_usec = timeout_ % 1000 * 1000; - } -#ifdef ZMQ_HAVE_WINDOWS - int rc = select (0, &fds, NULL, NULL, - timeout_ >= 0 ? &timeout : NULL); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = select (r + 1, &fds, NULL, NULL, - timeout_ >= 0 ? &timeout : NULL); - if (unlikely (rc < 0)) { - errno_assert (errno == EINTR); - return -1; - } -#endif - if (unlikely (rc == 0)) { - errno = EAGAIN; - return -1; - } - zmq_assert (rc == 1); - return 0; - -#else -#error -#endif -} - -void zmq::signaler_t::recv () -{ - // Attempt to read a signal. -#if defined ZMQ_HAVE_EVENTFD - uint64_t dummy; - ssize_t sz = read (r, &dummy, sizeof (dummy)); - errno_assert (sz == sizeof (dummy)); - - // If we accidentally grabbed the next signal along with the current - // one, return it back to the eventfd object. - if (unlikely (dummy == 2)) { - const uint64_t inc = 1; - ssize_t sz2 = write (w, &inc, sizeof (inc)); - errno_assert (sz2 == sizeof (inc)); - return; - } - - zmq_assert (dummy == 1); -#else - unsigned char dummy; -#if defined ZMQ_HAVE_WINDOWS - int nbytes = ::recv (r, (char*) &dummy, sizeof (dummy), 0); - wsa_assert (nbytes != SOCKET_ERROR); -#else - ssize_t nbytes = ::recv (r, &dummy, sizeof (dummy), 0); - errno_assert (nbytes >= 0); -#endif - zmq_assert (nbytes == sizeof (dummy)); - zmq_assert (dummy == 0); -#endif -} - -#ifdef HAVE_FORK -void zmq::signaler_t::forked() -{ - // Close file descriptors created in the parent and create new pair - close (r); - close (w); - make_fdpair (&r, &w); -} -#endif - -// Returns -1 if we could not make the socket pair successfully -int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_) -{ -#if defined ZMQ_HAVE_EVENTFD - fd_t fd = eventfd (0, 0); - if (fd == -1) { - errno_assert (errno == ENFILE || errno == EMFILE); - *w_ = *r_ = -1; - return -1; - } - else { - *w_ = *r_ = fd; - return 0; - } - -#elif defined ZMQ_HAVE_WINDOWS -# if !defined _WIN32_WCE - // Windows CE does not manage security attributes - SECURITY_DESCRIPTOR sd; - SECURITY_ATTRIBUTES sa; - memset (&sd, 0, sizeof (sd)); - memset (&sa, 0, sizeof (sa)); - - InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE); - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = &sd; -# endif - - // This function has to be in a system-wide critical section so that - // two instances of the library don't accidentally create signaler - // crossing the process boundary. - // We'll use named event object to implement the critical section. - // Note that if the event object already exists, the CreateEvent requests - // EVENT_ALL_ACCESS access right. If this fails, we try to open - // the event object asking for SYNCHRONIZE access only. -# if !defined _WIN32_WCE - HANDLE sync = CreateEvent (&sa, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync")); -# else - HANDLE sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync")); -# endif - if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED) - sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE, - FALSE, TEXT ("Global\\zmq-signaler-port-sync")); - - win_assert (sync != NULL); - - // Windows has no 'socketpair' function. CreatePipe is no good as pipe - // handles cannot be polled on. Here we create the socketpair by hand. - *w_ = INVALID_SOCKET; - *r_ = INVALID_SOCKET; - - // Create listening socket. - SOCKET listener; - listener = open_socket (AF_INET, SOCK_STREAM, 0); - wsa_assert (listener != INVALID_SOCKET); - - // Set SO_REUSEADDR and TCP_NODELAY on listening socket. - BOOL so_reuseaddr = 1; - int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, - (char *)&so_reuseaddr, sizeof (so_reuseaddr)); - wsa_assert (rc != SOCKET_ERROR); - BOOL tcp_nodelay = 1; - rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, - (char *)&tcp_nodelay, sizeof (tcp_nodelay)); - wsa_assert (rc != SOCKET_ERROR); - - // Init sockaddr to signaler port. - struct sockaddr_in addr; - memset (&addr, 0, sizeof (addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - addr.sin_port = htons (signaler_port); - - // Create the writer socket. - *w_ = open_socket (AF_INET, SOCK_STREAM, 0); - wsa_assert (*w_ != INVALID_SOCKET); - - // Set TCP_NODELAY on writer socket. - rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, - (char *)&tcp_nodelay, sizeof (tcp_nodelay)); - wsa_assert (rc != SOCKET_ERROR); - - // Enter the critical section. - DWORD dwrc = WaitForSingleObject (sync, INFINITE); - zmq_assert (dwrc == WAIT_OBJECT_0); - - // Bind listening socket to signaler port. - rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr)); - - // Listen for incoming connections. - if (rc != SOCKET_ERROR) - rc = listen (listener, 1); - - // Connect writer to the listener. - if (rc != SOCKET_ERROR) - rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr)); - - // Accept connection from writer. - if (rc != SOCKET_ERROR) - *r_ = accept (listener, NULL, NULL); - - // Save errno if error occurred in bind/listen/connect/accept. - int saved_errno = 0; - if (*r_ == INVALID_SOCKET) - saved_errno = WSAGetLastError (); - - // We don't need the listening socket anymore. Close it. - closesocket (listener); - - // Exit the critical section. - BOOL brc = SetEvent (sync); - win_assert (brc != 0); - - // Release the kernel object - brc = CloseHandle (sync); - win_assert (brc != 0); - - if (*r_ != INVALID_SOCKET) { -# if !defined _WIN32_WCE - // On Windows, preventing sockets to be inherited by child processes. - brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0); - win_assert (brc); -# endif - return 0; - } - else { - // Cleanup writer if connection failed - if (*w_ != INVALID_SOCKET) { - rc = closesocket (*w_); - wsa_assert (rc != SOCKET_ERROR); - *w_ = INVALID_SOCKET; - } - // Set errno from saved value - errno = wsa_error_to_errno (saved_errno); - return -1; - } - -#elif defined ZMQ_HAVE_OPENVMS - - // Whilst OpenVMS supports socketpair - it maps to AF_INET only. Further, - // it does not set the socket options TCP_NODELAY and TCP_NODELACK which - // can lead to performance problems. - // - // The bug will be fixed in V5.6 ECO4 and beyond. In the meantime, we'll - // create the socket pair manually. - struct sockaddr_in lcladdr; - memset (&lcladdr, 0, sizeof (lcladdr)); - lcladdr.sin_family = AF_INET; - lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - lcladdr.sin_port = 0; - - int listener = open_socket (AF_INET, SOCK_STREAM, 0); - errno_assert (listener != -1); - - int on = 1; - int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)); - errno_assert (rc != -1); - - rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on)); - errno_assert (rc != -1); - - rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr)); - errno_assert (rc != -1); - - socklen_t lcladdr_len = sizeof (lcladdr); - - rc = getsockname (listener, (struct sockaddr*) &lcladdr, &lcladdr_len); - errno_assert (rc != -1); - - rc = listen (listener, 1); - errno_assert (rc != -1); - - *w_ = open_socket (AF_INET, SOCK_STREAM, 0); - errno_assert (*w_ != -1); - - rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)); - errno_assert (rc != -1); - - rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on)); - errno_assert (rc != -1); - - rc = connect (*w_, (struct sockaddr*) &lcladdr, sizeof (lcladdr)); - errno_assert (rc != -1); - - *r_ = accept (listener, NULL, NULL); - errno_assert (*r_ != -1); - - close (listener); - - return 0; - -#else - // All other implementations support socketpair() - int sv [2]; - int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv); - if (rc == -1) { - errno_assert (errno == ENFILE || errno == EMFILE); - *w_ = *r_ = -1; - return -1; - } - else { - *w_ = sv [0]; - *r_ = sv [1]; - return 0; - } -#endif -} - -#if defined ZMQ_SIGNALER_WAIT_BASED_ON_SELECT -#undef ZMQ_SIGNALER_WAIT_BASED_ON_SELECT -#endif -#if defined ZMQ_SIGNALER_WAIT_BASED_ON_POLL -#undef ZMQ_SIGNALER_WAIT_BASED_ON_POLL -#endif - diff --git a/src/signaler.hpp b/src/signaler.hpp deleted file mode 100644 index 3e0d4f6..0000000 --- a/src/signaler.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_SIGNALER_HPP_INCLUDED__ -#define __ZMQ_SIGNALER_HPP_INCLUDED__ - -#ifdef HAVE_FORK -#include <unistd.h> -#endif - -#include "fd.hpp" - -namespace zmq -{ - - // This is a cross-platform equivalent to signal_fd. However, as opposed - // to signal_fd there can be at most one signal in the signaler at any - // given moment. Attempt to send a signal before receiving the previous - // one will result in undefined behaviour. - - class signaler_t - { - public: - - signaler_t (); - ~signaler_t (); - - fd_t get_fd (); - void send (); - int wait (int timeout_); - void recv (); - -#ifdef HAVE_FORK - // close the file descriptors in a forked child process so that they - // do not interfere with the context in the parent process. - void forked(); -#endif - - private: - - // Creates a pair of filedescriptors that will be used - // to pass the signals. - static int make_fdpair (fd_t *r_, fd_t *w_); - - // Underlying write & read file descriptor - // Will be -1 if we exceeded number of available handles - fd_t w; - fd_t r; - - // Disable copying of signaler_t object. - signaler_t (const signaler_t&); - const signaler_t &operator = (const signaler_t&); - -#ifdef HAVE_FORK - // the process that created this context. Used to detect forking. - pid_t pid; - // idempotent close of file descriptors that is safe to use by destructor - // and forked(). - void close_internal(); -#endif - }; -} - -#endif diff --git a/src/socket_base.cpp b/src/socket_base.cpp deleted file mode 100644 index a1b1ec0..0000000 --- a/src/socket_base.cpp +++ /dev/null @@ -1,1271 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <new> -#include <string> -#include <algorithm> - -#include "platform.hpp" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#if defined _MSC_VER -#if defined _WIN32_WCE -#include <cmnintrin.h> -#else -#include <intrin.h> -#endif -#endif -#else -#include <unistd.h> -#endif - -#include "socket_base.hpp" -#include "tcp_listener.hpp" -#include "ipc_listener.hpp" -#include "tcp_connecter.hpp" -#include "io_thread.hpp" -#include "session_base.hpp" -#include "config.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "ctx.hpp" -#include "platform.hpp" -#include "likely.hpp" -#include "msg.hpp" -#include "address.hpp" -#include "ipc_address.hpp" -#include "tcp_address.hpp" -#ifdef ZMQ_HAVE_OPENPGM -#include "pgm_socket.hpp" -#endif - -#include "pair.hpp" -#include "pub.hpp" -#include "sub.hpp" -#include "req.hpp" -#include "rep.hpp" -#include "pull.hpp" -#include "push.hpp" -#include "dealer.hpp" -#include "router.hpp" -#include "xpub.hpp" -#include "xsub.hpp" -#include "stream.hpp" - -bool zmq::socket_base_t::check_tag () -{ - return tag == 0xbaddecaf; -} - -zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_, - uint32_t tid_, int sid_) -{ - socket_base_t *s = NULL; - switch (type_) { - case ZMQ_PAIR: - s = new (std::nothrow) pair_t (parent_, tid_, sid_); - break; - case ZMQ_PUB: - s = new (std::nothrow) pub_t (parent_, tid_, sid_); - break; - case ZMQ_SUB: - s = new (std::nothrow) sub_t (parent_, tid_, sid_); - break; - case ZMQ_REQ: - s = new (std::nothrow) req_t (parent_, tid_, sid_); - break; - case ZMQ_REP: - s = new (std::nothrow) rep_t (parent_, tid_, sid_); - break; - case ZMQ_DEALER: - s = new (std::nothrow) dealer_t (parent_, tid_, sid_); - break; - case ZMQ_ROUTER: - s = new (std::nothrow) router_t (parent_, tid_, sid_); - break; - case ZMQ_PULL: - s = new (std::nothrow) pull_t (parent_, tid_, sid_); - break; - case ZMQ_PUSH: - s = new (std::nothrow) push_t (parent_, tid_, sid_); - break; - case ZMQ_XPUB: - s = new (std::nothrow) xpub_t (parent_, tid_, sid_); - break; - case ZMQ_XSUB: - s = new (std::nothrow) xsub_t (parent_, tid_, sid_); - break; - case ZMQ_STREAM: - s = new (std::nothrow) stream_t (parent_, tid_, sid_); - break; - default: - errno = EINVAL; - return NULL; - } - if (s->mailbox.get_fd () == retired_fd) - return NULL; - - alloc_assert (s); - return s; -} - -zmq::socket_base_t::socket_base_t (ctx_t *parent_, uint32_t tid_, int sid_) : - own_t (parent_, tid_), - tag (0xbaddecaf), - ctx_terminated (false), - destroyed (false), - last_tsc (0), - ticks (0), - rcvmore (false), - monitor_socket (NULL), - monitor_events (0) -{ - options.socket_id = sid_; - options.ipv6 = (parent_->get (ZMQ_IPV6) != 0); -} - -zmq::socket_base_t::~socket_base_t () -{ - stop_monitor (); - zmq_assert (destroyed); -} - -zmq::mailbox_t *zmq::socket_base_t::get_mailbox () -{ - return &mailbox; -} - -void zmq::socket_base_t::stop () -{ - // Called by ctx when it is terminated (zmq_term). - // 'stop' command is sent from the threads that called zmq_term to - // the thread owning the socket. This way, blocking call in the - // owner thread can be interrupted. - send_stop (); -} - -int zmq::socket_base_t::parse_uri (const char *uri_, - std::string &protocol_, std::string &address_) -{ - zmq_assert (uri_ != NULL); - - std::string uri (uri_); - std::string::size_type pos = uri.find ("://"); - if (pos == std::string::npos) { - errno = EINVAL; - return -1; - } - protocol_ = uri.substr (0, pos); - address_ = uri.substr (pos + 3); - - if (protocol_.empty () || address_.empty ()) { - errno = EINVAL; - return -1; - } - return 0; -} - -int zmq::socket_base_t::check_protocol (const std::string &protocol_) -{ - // First check out whether the protcol is something we are aware of. - if (protocol_ != "inproc" && protocol_ != "ipc" && protocol_ != "tcp" && - protocol_ != "pgm" && protocol_ != "epgm") { - errno = EPROTONOSUPPORT; - return -1; - } - - // If 0MQ is not compiled with OpenPGM, pgm and epgm transports - // are not avaialble. -#if !defined ZMQ_HAVE_OPENPGM - if (protocol_ == "pgm" || protocol_ == "epgm") { - errno = EPROTONOSUPPORT; - return -1; - } -#endif - - // IPC transport is not available on Windows and OpenVMS. -#if defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS - if (protocol_ == "ipc") { - // Unknown protocol. - errno = EPROTONOSUPPORT; - return -1; - } -#endif - - // Check whether socket type and transport protocol match. - // Specifically, multicast protocols can't be combined with - // bi-directional messaging patterns (socket types). - if ((protocol_ == "pgm" || protocol_ == "epgm") && - options.type != ZMQ_PUB && options.type != ZMQ_SUB && - options.type != ZMQ_XPUB && options.type != ZMQ_XSUB) { - errno = ENOCOMPATPROTO; - return -1; - } - - // Protocol is available. - return 0; -} - -void zmq::socket_base_t::attach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // First, register the pipe so that we can terminate it later on. - pipe_->set_event_sink (this); - pipes.push_back (pipe_); - - // Let the derived socket type know about new pipe. - xattach_pipe (pipe_, subscribe_to_all_); - - // If the socket is already being closed, ask any new pipes to terminate - // straight away. - if (is_terminating ()) { - register_term_acks (1); - pipe_->terminate (false); - } -} - -int zmq::socket_base_t::setsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // First, check whether specific socket type overloads the option. - int rc = xsetsockopt (option_, optval_, optvallen_); - if (rc == 0 || errno != EINVAL) - return rc; - - // If the socket type doesn't support the option, pass it to - // the generic option parser. - return options.setsockopt (option_, optval_, optvallen_); -} - -int zmq::socket_base_t::getsockopt (int option_, void *optval_, - size_t *optvallen_) -{ - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - if (option_ == ZMQ_RCVMORE) { - if (*optvallen_ < sizeof (int)) { - errno = EINVAL; - return -1; - } - *((int*) optval_) = rcvmore ? 1 : 0; - *optvallen_ = sizeof (int); - return 0; - } - - if (option_ == ZMQ_FD) { - if (*optvallen_ < sizeof (fd_t)) { - errno = EINVAL; - return -1; - } - *((fd_t*) optval_) = mailbox.get_fd (); - *optvallen_ = sizeof (fd_t); - return 0; - } - - if (option_ == ZMQ_EVENTS) { - if (*optvallen_ < sizeof (int)) { - errno = EINVAL; - return -1; - } - int rc = process_commands (0, false); - if (rc != 0 && (errno == EINTR || errno == ETERM)) - return -1; - errno_assert (rc == 0); - *((int*) optval_) = 0; - if (has_out ()) - *((int*) optval_) |= ZMQ_POLLOUT; - if (has_in ()) - *((int*) optval_) |= ZMQ_POLLIN; - *optvallen_ = sizeof (int); - return 0; - } - - if (option_ == ZMQ_LAST_ENDPOINT) { - if (*optvallen_ < last_endpoint.size () + 1) { - errno = EINVAL; - return -1; - } - strcpy (static_cast <char *> (optval_), last_endpoint.c_str ()); - *optvallen_ = last_endpoint.size () + 1; - return 0; - } - - return options.getsockopt (option_, optval_, optvallen_); -} - -int zmq::socket_base_t::bind (const char *addr_) -{ - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Process pending commands, if any. - int rc = process_commands (0, false); - if (unlikely (rc != 0)) - return -1; - - // Parse addr_ string. - std::string protocol; - std::string address; - rc = parse_uri (addr_, protocol, address); - if (rc != 0) - return -1; - - rc = check_protocol (protocol); - if (rc != 0) - return -1; - - if (protocol == "inproc") { - endpoint_t endpoint = {this, options}; - int rc = register_endpoint (addr_, endpoint); - if (rc == 0) { - connect_pending(addr_, this); - last_endpoint.assign (addr_); - } - return rc; - } - - if (protocol == "pgm" || protocol == "epgm") { - // For convenience's sake, bind can be used interchageable with - // connect for PGM and EPGM transports. - return connect (addr_); - } - - // Remaining trasnports require to be run in an I/O thread, so at this - // point we'll choose one. - io_thread_t *io_thread = choose_io_thread (options.affinity); - if (!io_thread) { - errno = EMTHREAD; - return -1; - } - - if (protocol == "tcp") { - tcp_listener_t *listener = new (std::nothrow) tcp_listener_t ( - io_thread, this, options); - alloc_assert (listener); - int rc = listener->set_address (address.c_str ()); - if (rc != 0) { - delete listener; - event_bind_failed (address, zmq_errno()); - return -1; - } - - // Save last endpoint URI - listener->get_address (last_endpoint); - - add_endpoint (addr_, (own_t *) listener, NULL); - return 0; - } - -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - if (protocol == "ipc") { - ipc_listener_t *listener = new (std::nothrow) ipc_listener_t ( - io_thread, this, options); - alloc_assert (listener); - int rc = listener->set_address (address.c_str ()); - if (rc != 0) { - delete listener; - event_bind_failed (address, zmq_errno()); - return -1; - } - - // Save last endpoint URI - listener->get_address (last_endpoint); - - add_endpoint (addr_, (own_t *) listener, NULL); - return 0; - } -#endif - - zmq_assert (false); - return -1; -} - -int zmq::socket_base_t::connect (const char *addr_) -{ - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Process pending commands, if any. - int rc = process_commands (0, false); - if (unlikely (rc != 0)) - return -1; - - // Parse addr_ string. - std::string protocol; - std::string address; - rc = parse_uri (addr_, protocol, address); - if (rc != 0) - return -1; - - rc = check_protocol (protocol); - if (rc != 0) - return -1; - - if (protocol == "inproc") { - - // TODO: inproc connect is specific with respect to creating pipes - // as there's no 'reconnect' functionality implemented. Once that - // is in place we should follow generic pipe creation algorithm. - - // Find the peer endpoint. - endpoint_t peer = find_endpoint (addr_); - - // The total HWM for an inproc connection should be the sum of - // the binder's HWM and the connector's HWM. - int sndhwm = 0; - if (peer.socket == NULL) - sndhwm = options.sndhwm; - else if (options.sndhwm != 0 && peer.options.rcvhwm != 0) - sndhwm = options.sndhwm + peer.options.rcvhwm; - int rcvhwm = 0; - if (peer.socket == NULL) - rcvhwm = options.rcvhwm; - else if (options.rcvhwm != 0 && peer.options.sndhwm != 0) - rcvhwm = options.rcvhwm + peer.options.sndhwm; - - // Create a bi-directional pipe to connect the peers. - object_t *parents [2] = {this, peer.socket == NULL ? this : peer.socket}; - pipe_t *new_pipes [2] = {NULL, NULL}; - - bool conflate = options.conflate && - (options.type == ZMQ_DEALER || - options.type == ZMQ_PULL || - options.type == ZMQ_PUSH || - options.type == ZMQ_PUB || - options.type == ZMQ_SUB); - - int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm}; - bool conflates [2] = {conflate, conflate}; - int rc = pipepair (parents, new_pipes, hwms, conflates); - errno_assert (rc == 0); - - // Attach local end of the pipe to this socket object. - attach_pipe (new_pipes [0]); - - if (!peer.socket) - { - endpoint_t endpoint = {this, options}; - pending_connection_t pending_connection = {endpoint, new_pipes [0], new_pipes [1]}; - pend_connection (addr_, pending_connection); - } - else - { - // If required, send the identity of the local socket to the peer. - if (peer.options.recv_identity) { - - msg_t id; - rc = id.init_size (options.identity_size); - errno_assert (rc == 0); - memcpy (id.data (), options.identity, options.identity_size); - id.set_flags (msg_t::identity); - bool written = new_pipes [0]->write (&id); - zmq_assert (written); - new_pipes [0]->flush (); - } - - // If required, send the identity of the peer to the local socket. - if (options.recv_identity) { - msg_t id; - rc = id.init_size (peer.options.identity_size); - errno_assert (rc == 0); - memcpy (id.data (), peer.options.identity, peer.options.identity_size); - id.set_flags (msg_t::identity); - bool written = new_pipes [1]->write (&id); - zmq_assert (written); - new_pipes [1]->flush (); - } - - // Attach remote end of the pipe to the peer socket. Note that peer's - // seqnum was incremented in find_endpoint function. We don't need it - // increased here. - send_bind (peer.socket, new_pipes [1], false); - } - - // Save last endpoint URI - last_endpoint.assign (addr_); - - // remember inproc connections for disconnect - inprocs.insert (inprocs_t::value_type (std::string (addr_), new_pipes[0])); - - return 0; - } - - // Choose the I/O thread to run the session in. - io_thread_t *io_thread = choose_io_thread (options.affinity); - if (!io_thread) { - errno = EMTHREAD; - return -1; - } - - address_t *paddr = new (std::nothrow) address_t (protocol, address); - alloc_assert (paddr); - - // Resolve address (if needed by the protocol) - if (protocol == "tcp") { - paddr->resolved.tcp_addr = new (std::nothrow) tcp_address_t (); - alloc_assert (paddr->resolved.tcp_addr); - int rc = paddr->resolved.tcp_addr->resolve ( - address.c_str (), false, options.ipv6); - if (rc != 0) { - delete paddr; - return -1; - } - } -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - else - if (protocol == "ipc") { - paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); - alloc_assert (paddr->resolved.ipc_addr); - int rc = paddr->resolved.ipc_addr->resolve (address.c_str ()); - if (rc != 0) { - delete paddr; - return -1; - } - } -#endif -#ifdef ZMQ_HAVE_OPENPGM - if (protocol == "pgm" || protocol == "epgm") { - struct pgm_addrinfo_t *res = NULL; - uint16_t port_number = 0; - int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number); - if (res != NULL) - pgm_freeaddrinfo (res); - if (rc != 0 || port_number == 0) - return -1; - } -#endif - // Create session. - session_base_t *session = session_base_t::create (io_thread, true, this, - options, paddr); - errno_assert (session); - - // PGM does not support subscription forwarding; ask for all data to be - // sent to this pipe. - bool subscribe_to_all = protocol == "pgm" || protocol == "epgm"; - pipe_t *newpipe = NULL; - - if (options.immediate != 1 || subscribe_to_all) { - // Create a bi-directional pipe. - object_t *parents [2] = {this, session}; - pipe_t *new_pipes [2] = {NULL, NULL}; - - bool conflate = options.conflate && - (options.type == ZMQ_DEALER || - options.type == ZMQ_PULL || - options.type == ZMQ_PUSH || - options.type == ZMQ_PUB || - options.type == ZMQ_SUB); - - int hwms [2] = {conflate? -1 : options.sndhwm, - conflate? -1 : options.rcvhwm}; - bool conflates [2] = {conflate, conflate}; - rc = pipepair (parents, new_pipes, hwms, conflates); - errno_assert (rc == 0); - - // Attach local end of the pipe to the socket object. - attach_pipe (new_pipes [0], subscribe_to_all); - newpipe = new_pipes [0]; - - // Attach remote end of the pipe to the session object later on. - session->attach_pipe (new_pipes [1]); - } - - // Save last endpoint URI - paddr->to_string (last_endpoint); - - add_endpoint (addr_, (own_t *) session, newpipe); - return 0; -} - -void zmq::socket_base_t::add_endpoint (const char *addr_, own_t *endpoint_, pipe_t *pipe) -{ - // Activate the session. Make it a child of this socket. - launch_child (endpoint_); - endpoints.insert (endpoints_t::value_type (std::string (addr_), endpoint_pipe_t(endpoint_, pipe))); -} - -int zmq::socket_base_t::term_endpoint (const char *addr_) -{ - // Check whether the library haven't been shut down yet. - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Check whether endpoint address passed to the function is valid. - if (unlikely (!addr_)) { - errno = EINVAL; - return -1; - } - - // Process pending commands, if any, since there could be pending unprocessed process_own()'s - // (from launch_child() for example) we're asked to terminate now. - int rc = process_commands (0, false); - if (unlikely (rc != 0)) - return -1; - - // Parse addr_ string. - std::string protocol; - std::string address; - rc = parse_uri (addr_, protocol, address); - if (rc != 0) - return -1; - - rc = check_protocol (protocol); - if (rc != 0) - return -1; - - // Disconnect an inproc socket - if (protocol == "inproc") { - std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_)); - if (range.first == range.second) { - errno = ENOENT; - return -1; - } - - for (inprocs_t::iterator it = range.first; it != range.second; ++it) - it->second->terminate(true); - inprocs.erase (range.first, range.second); - return 0; - } - - // Find the endpoints range (if any) corresponding to the addr_ string. - std::pair <endpoints_t::iterator, endpoints_t::iterator> range = endpoints.equal_range (std::string (addr_)); - if (range.first == range.second) { - errno = ENOENT; - return -1; - } - - for (endpoints_t::iterator it = range.first; it != range.second; ++it) { - // If we have an associated pipe, terminate it. - if (it->second.second != NULL) - it->second.second->terminate(false); - term_child (it->second.first); - } - endpoints.erase (range.first, range.second); - return 0; -} - -int zmq::socket_base_t::send (msg_t *msg_, int flags_) -{ - // Check whether the library haven't been shut down yet. - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Check whether message passed to the function is valid. - if (unlikely (!msg_ || !msg_->check ())) { - errno = EFAULT; - return -1; - } - - // Process pending commands, if any. - int rc = process_commands (0, true); - if (unlikely (rc != 0)) - return -1; - - // Clear any user-visible flags that are set on the message. - msg_->reset_flags (msg_t::more); - - // At this point we impose the flags on the message. - if (flags_ & ZMQ_SNDMORE) - msg_->set_flags (msg_t::more); - - // Try to send the message. - rc = xsend (msg_); - if (rc == 0) - return 0; - if (unlikely (errno != EAGAIN)) - return -1; - - // In case of non-blocking send we'll simply propagate - // the error - including EAGAIN - up the stack. - if (flags_ & ZMQ_DONTWAIT || options.sndtimeo == 0) - return -1; - - // Compute the time when the timeout should occur. - // If the timeout is infinite, don't care. - int timeout = options.sndtimeo; - uint64_t end = timeout < 0 ? 0 : (clock.now_ms () + timeout); - - // Oops, we couldn't send the message. Wait for the next - // command, process it and try to send the message again. - // If timeout is reached in the meantime, return EAGAIN. - while (true) { - if (unlikely (process_commands (timeout, false) != 0)) - return -1; - rc = xsend (msg_); - if (rc == 0) - break; - if (unlikely (errno != EAGAIN)) - return -1; - if (timeout > 0) { - timeout = (int) (end - clock.now_ms ()); - if (timeout <= 0) { - errno = EAGAIN; - return -1; - } - } - } - return 0; -} - -int zmq::socket_base_t::recv (msg_t *msg_, int flags_) -{ - // Check whether the library haven't been shut down yet. - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Check whether message passed to the function is valid. - if (unlikely (!msg_ || !msg_->check ())) { - errno = EFAULT; - return -1; - } - - // Once every inbound_poll_rate messages check for signals and process - // incoming commands. This happens only if we are not polling altogether - // because there are messages available all the time. If poll occurs, - // ticks is set to zero and thus we avoid this code. - // - // Note that 'recv' uses different command throttling algorithm (the one - // described above) from the one used by 'send'. This is because counting - // ticks is more efficient than doing RDTSC all the time. - if (++ticks == inbound_poll_rate) { - if (unlikely (process_commands (0, false) != 0)) - return -1; - ticks = 0; - } - - // Get the message. - int rc = xrecv (msg_); - if (unlikely (rc != 0 && errno != EAGAIN)) - return -1; - - // If we have the message, return immediately. - if (rc == 0) { - extract_flags (msg_); - return 0; - } - - // If the message cannot be fetched immediately, there are two scenarios. - // For non-blocking recv, commands are processed in case there's an - // activate_reader command already waiting int a command pipe. - // If it's not, return EAGAIN. - if (flags_ & ZMQ_DONTWAIT || options.rcvtimeo == 0) { - if (unlikely (process_commands (0, false) != 0)) - return -1; - ticks = 0; - - rc = xrecv (msg_); - if (rc < 0) - return rc; - extract_flags (msg_); - return 0; - } - - // Compute the time when the timeout should occur. - // If the timeout is infinite, don't care. - int timeout = options.rcvtimeo; - uint64_t end = timeout < 0 ? 0 : (clock.now_ms () + timeout); - - // In blocking scenario, commands are processed over and over again until - // we are able to fetch a message. - bool block = (ticks != 0); - while (true) { - if (unlikely (process_commands (block ? timeout : 0, false) != 0)) - return -1; - rc = xrecv (msg_); - if (rc == 0) { - ticks = 0; - break; - } - if (unlikely (errno != EAGAIN)) - return -1; - block = true; - if (timeout > 0) { - timeout = (int) (end - clock.now_ms ()); - if (timeout <= 0) { - errno = EAGAIN; - return -1; - } - } - } - - extract_flags (msg_); - return 0; -} - -int zmq::socket_base_t::close () -{ - // Mark the socket as dead - tag = 0xdeadbeef; - - // Transfer the ownership of the socket from this application thread - // to the reaper thread which will take care of the rest of shutdown - // process. - send_reap (this); - - return 0; -} - -bool zmq::socket_base_t::has_in () -{ - return xhas_in (); -} - -bool zmq::socket_base_t::has_out () -{ - return xhas_out (); -} - -void zmq::socket_base_t::start_reaping (poller_t *poller_) -{ - // Plug the socket to the reaper thread. - poller = poller_; - handle = poller->add_fd (mailbox.get_fd (), this); - poller->set_pollin (handle); - - // Initialise the termination and check whether it can be deallocated - // immediately. - terminate (); - check_destroy (); -} - -int zmq::socket_base_t::process_commands (int timeout_, bool throttle_) -{ - int rc; - command_t cmd; - if (timeout_ != 0) { - - // If we are asked to wait, simply ask mailbox to wait. - rc = mailbox.recv (&cmd, timeout_); - } - else { - - // If we are asked not to wait, check whether we haven't processed - // commands recently, so that we can throttle the new commands. - - // Get the CPU's tick counter. If 0, the counter is not available. - uint64_t tsc = zmq::clock_t::rdtsc (); - - // Optimised version of command processing - it doesn't have to check - // for incoming commands each time. It does so only if certain time - // elapsed since last command processing. Command delay varies - // depending on CPU speed: It's ~1ms on 3GHz CPU, ~2ms on 1.5GHz CPU - // etc. The optimisation makes sense only on platforms where getting - // a timestamp is a very cheap operation (tens of nanoseconds). - if (tsc && throttle_) { - - // Check whether TSC haven't jumped backwards (in case of migration - // between CPU cores) and whether certain time have elapsed since - // last command processing. If it didn't do nothing. - if (tsc >= last_tsc && tsc - last_tsc <= max_command_delay) - return 0; - last_tsc = tsc; - } - - // Check whether there are any commands pending for this thread. - rc = mailbox.recv (&cmd, 0); - } - - // Process all available commands. - while (rc == 0) { - cmd.destination->process_command (cmd); - rc = mailbox.recv (&cmd, 0); - } - - if (errno == EINTR) - return -1; - - zmq_assert (errno == EAGAIN); - - if (ctx_terminated) { - errno = ETERM; - return -1; - } - - return 0; -} - -void zmq::socket_base_t::process_stop () -{ - // Here, someone have called zmq_term while the socket was still alive. - // We'll remember the fact so that any blocking call is interrupted and any - // further attempt to use the socket will return ETERM. The user is still - // responsible for calling zmq_close on the socket though! - stop_monitor (); - ctx_terminated = true; -} - -void zmq::socket_base_t::process_bind (pipe_t *pipe_) -{ - attach_pipe (pipe_); -} - -void zmq::socket_base_t::process_term (int linger_) -{ - // Unregister all inproc endpoints associated with this socket. - // Doing this we make sure that no new pipes from other sockets (inproc) - // will be initiated. - unregister_endpoints (this); - - // Ask all attached pipes to terminate. - for (pipes_t::size_type i = 0; i != pipes.size (); ++i) - pipes [i]->terminate (false); - register_term_acks ((int) pipes.size ()); - - // Continue the termination process immediately. - own_t::process_term (linger_); -} - -void zmq::socket_base_t::process_destroy () -{ - destroyed = true; -} - -int zmq::socket_base_t::xsetsockopt (int, const void *, size_t) -{ - errno = EINVAL; - return -1; -} - -bool zmq::socket_base_t::xhas_out () -{ - return false; -} - -int zmq::socket_base_t::xsend (msg_t *) -{ - errno = ENOTSUP; - return -1; -} - -bool zmq::socket_base_t::xhas_in () -{ - return false; -} - -int zmq::socket_base_t::xrecv (msg_t *) -{ - errno = ENOTSUP; - return -1; -} - -void zmq::socket_base_t::xread_activated (pipe_t *) -{ - zmq_assert (false); -} -void zmq::socket_base_t::xwrite_activated (pipe_t *) -{ - zmq_assert (false); -} - -void zmq::socket_base_t::xhiccuped (pipe_t *) -{ - zmq_assert (false); -} - -void zmq::socket_base_t::in_event () -{ - // This function is invoked only once the socket is running in the context - // of the reaper thread. Process any commands from other threads/sockets - // that may be available at the moment. Ultimately, the socket will - // be destroyed. - process_commands (0, false); - check_destroy (); -} - -void zmq::socket_base_t::out_event () -{ - zmq_assert (false); -} - -void zmq::socket_base_t::timer_event (int) -{ - zmq_assert (false); -} - -void zmq::socket_base_t::check_destroy () -{ - // If the object was already marked as destroyed, finish the deallocation. - if (destroyed) { - - // Remove the socket from the reaper's poller. - poller->rm_fd (handle); - - // Remove the socket from the context. - destroy_socket (this); - - // Notify the reaper about the fact. - send_reaped (); - - // Deallocate. - own_t::process_destroy (); - } -} - -void zmq::socket_base_t::read_activated (pipe_t *pipe_) -{ - xread_activated (pipe_); -} - -void zmq::socket_base_t::write_activated (pipe_t *pipe_) -{ - xwrite_activated (pipe_); -} - -void zmq::socket_base_t::hiccuped (pipe_t *pipe_) -{ - if (options.immediate == 1) - pipe_->terminate (false); - else - // Notify derived sockets of the hiccup - xhiccuped (pipe_); -} - -void zmq::socket_base_t::pipe_terminated (pipe_t *pipe_) -{ - // Notify the specific socket type about the pipe termination. - xpipe_terminated (pipe_); - - // Remove pipe from inproc pipes - for (inprocs_t::iterator it = inprocs.begin(); it != inprocs.end(); ++it) { - if (it->second == pipe_) { - inprocs.erase(it); - break; - } - } - - // Remove the pipe from the list of attached pipes and confirm its - // termination if we are already shutting down. - pipes.erase (pipe_); - if (is_terminating ()) - unregister_term_ack (); -} - -void zmq::socket_base_t::extract_flags (msg_t *msg_) -{ - // Test whether IDENTITY flag is valid for this socket type. - if (unlikely (msg_->flags () & msg_t::identity)) - zmq_assert (options.recv_identity); - - // Remove MORE flag. - rcvmore = msg_->flags () & msg_t::more ? true : false; -} - -int zmq::socket_base_t::monitor (const char *addr_, int events_) -{ - int rc; - if (unlikely (ctx_terminated)) { - errno = ETERM; - return -1; - } - - // Support deregistering monitoring endpoints as well - if (addr_ == NULL) { - stop_monitor (); - return 0; - } - - // Parse addr_ string. - std::string protocol; - std::string address; - rc = parse_uri (addr_, protocol, address); - if (rc != 0) - return -1; - - rc = check_protocol (protocol); - if (rc != 0) - return -1; - - // Event notification only supported over inproc:// - if (protocol != "inproc") { - errno = EPROTONOSUPPORT; - return -1; - } - - // Register events to monitor - monitor_events = events_; - monitor_socket = zmq_socket (get_ctx (), ZMQ_PAIR); - if (monitor_socket == NULL) - return -1; - - // Never block context termination on pending event messages - int linger = 0; - rc = zmq_setsockopt (monitor_socket, ZMQ_LINGER, &linger, sizeof (linger)); - if (rc == -1) - stop_monitor (); - - // Spawn the monitor socket endpoint - rc = zmq_bind (monitor_socket, addr_); - if (rc == -1) - stop_monitor (); - return rc; -} - -void zmq::socket_base_t::event_connected (std::string &addr_, int fd_) -{ - if (monitor_events & ZMQ_EVENT_CONNECTED) { - zmq_event_t event; - event.event = ZMQ_EVENT_CONNECTED; - event.value = fd_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_connect_delayed (std::string &addr_, int err_) -{ - if (monitor_events & ZMQ_EVENT_CONNECT_DELAYED) { - zmq_event_t event; - event.event = ZMQ_EVENT_CONNECT_DELAYED; - event.value = err_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_connect_retried (std::string &addr_, int interval_) -{ - if (monitor_events & ZMQ_EVENT_CONNECT_RETRIED) { - zmq_event_t event; - event.event = ZMQ_EVENT_CONNECT_RETRIED; - event.value = interval_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_listening (std::string &addr_, int fd_) -{ - if (monitor_events & ZMQ_EVENT_LISTENING) { - zmq_event_t event; - event.event = ZMQ_EVENT_LISTENING; - event.value = fd_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_bind_failed (std::string &addr_, int err_) -{ - if (monitor_events & ZMQ_EVENT_BIND_FAILED) { - zmq_event_t event; - event.event = ZMQ_EVENT_BIND_FAILED; - event.value = err_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_accepted (std::string &addr_, int fd_) -{ - if (monitor_events & ZMQ_EVENT_ACCEPTED) { - zmq_event_t event; - event.event = ZMQ_EVENT_ACCEPTED; - event.value = fd_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_accept_failed (std::string &addr_, int err_) -{ - if (monitor_events & ZMQ_EVENT_ACCEPT_FAILED) { - zmq_event_t event; - event.event = ZMQ_EVENT_ACCEPT_FAILED; - event.value= err_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_closed (std::string &addr_, int fd_) -{ - if (monitor_events & ZMQ_EVENT_CLOSED) { - zmq_event_t event; - event.event = ZMQ_EVENT_CLOSED; - event.value = fd_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_close_failed (std::string &addr_, int err_) -{ - if (monitor_events & ZMQ_EVENT_CLOSE_FAILED) { - zmq_event_t event; - event.event = ZMQ_EVENT_CLOSE_FAILED; - event.value = err_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::event_disconnected (std::string &addr_, int fd_) -{ - if (monitor_events & ZMQ_EVENT_DISCONNECTED) { - zmq_event_t event; - event.event = ZMQ_EVENT_DISCONNECTED; - event.value = fd_; - monitor_event (event, addr_); - } -} - -void zmq::socket_base_t::monitor_event (zmq_event_t event_, const std::string& addr_) -{ - if (monitor_socket) { - const uint16_t eid = (uint16_t)event_.event; - const uint32_t value = (uint32_t)event_.value; - // prepare and send first message frame - // containing event id and value - zmq_msg_t msg; - zmq_msg_init_size (&msg, sizeof(eid) + sizeof(value)); - char* data1 = (char*)zmq_msg_data(&msg); - memcpy (data1, &eid, sizeof(eid)); - memcpy (data1+sizeof(eid), &value, sizeof(value)); - zmq_sendmsg (monitor_socket, &msg, ZMQ_SNDMORE); - // prepare and send second message frame - // containing the address (endpoint) - zmq_msg_init_size (&msg, addr_.size()); - memcpy(zmq_msg_data(&msg), addr_.c_str(), addr_.size()); - zmq_sendmsg (monitor_socket, &msg, 0); - } -} - -void zmq::socket_base_t::stop_monitor() -{ - if (monitor_socket) { - if (monitor_events & ZMQ_EVENT_MONITOR_STOPPED) { - zmq_event_t event; - event.event = ZMQ_EVENT_MONITOR_STOPPED; - event.value = 0; - monitor_event (event, ""); - } - zmq_close (monitor_socket); - monitor_socket = NULL; - monitor_events = 0; - } -} diff --git a/src/socket_base.hpp b/src/socket_base.hpp deleted file mode 100644 index 8fbfa06..0000000 --- a/src/socket_base.hpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_SOCKET_BASE_HPP_INCLUDED__ -#define __ZMQ_SOCKET_BASE_HPP_INCLUDED__ - -#include <string> -#include <map> -#include <stdarg.h> - -#include "own.hpp" -#include "array.hpp" -#include "stdint.hpp" -#include "poller.hpp" -#include "atomic_counter.hpp" -#include "i_poll_events.hpp" -#include "mailbox.hpp" -#include "stdint.hpp" -#include "clock.hpp" -#include "pipe.hpp" - -extern "C" -{ - void zmq_free_event (void *data, void *hint); -} - -namespace zmq -{ - - class ctx_t; - class msg_t; - class pipe_t; - - class socket_base_t : - public own_t, - public array_item_t <>, - public i_poll_events, - public i_pipe_events - { - friend class reaper_t; - - public: - - // Returns false if object is not a socket. - bool check_tag (); - - // Create a socket of a specified type. - static socket_base_t *create (int type_, zmq::ctx_t *parent_, - uint32_t tid_, int sid_); - - // Returns the mailbox associated with this socket. - mailbox_t *get_mailbox (); - - // Interrupt blocking call if the socket is stuck in one. - // This function can be called from a different thread! - void stop (); - - // Interface for communication with the API layer. - int setsockopt (int option_, const void *optval_, size_t optvallen_); - int getsockopt (int option_, void *optval_, size_t *optvallen_); - int bind (const char *addr_); - int connect (const char *addr_); - int term_endpoint (const char *addr_); - int send (zmq::msg_t *msg_, int flags_); - int recv (zmq::msg_t *msg_, int flags_); - int close (); - - // These functions are used by the polling mechanism to determine - // which events are to be reported from this socket. - bool has_in (); - bool has_out (); - - // Using this function reaper thread ask the socket to regiter with - // its poller. - void start_reaping (poller_t *poller_); - - // i_poll_events implementation. This interface is used when socket - // is handled by the poller in the reaper thread. - void in_event (); - void out_event (); - void timer_event (int id_); - - // i_pipe_events interface implementation. - void read_activated (pipe_t *pipe_); - void write_activated (pipe_t *pipe_); - void hiccuped (pipe_t *pipe_); - void pipe_terminated (pipe_t *pipe_); - void lock(); - void unlock(); - - int monitor (const char *endpoint_, int events_); - - void event_connected (std::string &addr_, int fd_); - void event_connect_delayed (std::string &addr_, int err_); - void event_connect_retried (std::string &addr_, int interval_); - void event_listening (std::string &addr_, int fd_); - void event_bind_failed (std::string &addr_, int err_); - void event_accepted (std::string &addr_, int fd_); - void event_accept_failed (std::string &addr_, int err_); - void event_closed (std::string &addr_, int fd_); - void event_close_failed (std::string &addr_, int fd_); - void event_disconnected (std::string &addr_, int fd_); - - protected: - - socket_base_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - virtual ~socket_base_t (); - - // Concrete algorithms for the x- methods are to be defined by - // individual socket types. - virtual void xattach_pipe (zmq::pipe_t *pipe_, - bool subscribe_to_all_ = false) = 0; - - // The default implementation assumes there are no specific socket - // options for the particular socket type. If not so, overload this - // method. - virtual int xsetsockopt (int option_, const void *optval_, - size_t optvallen_); - - // The default implementation assumes that send is not supported. - virtual bool xhas_out (); - virtual int xsend (zmq::msg_t *msg_); - - // The default implementation assumes that recv in not supported. - virtual bool xhas_in (); - virtual int xrecv (zmq::msg_t *msg_); - - // i_pipe_events will be forwarded to these functions. - virtual void xread_activated (pipe_t *pipe_); - virtual void xwrite_activated (pipe_t *pipe_); - virtual void xhiccuped (pipe_t *pipe_); - virtual void xpipe_terminated (pipe_t *pipe_) = 0; - - // Delay actual destruction of the socket. - void process_destroy (); - - // Socket event data dispath - void monitor_event (zmq_event_t data_, const std::string& addr_); - - // Monitor socket cleanup - void stop_monitor (); - - private: - // Creates new endpoint ID and adds the endpoint to the map. - void add_endpoint (const char *addr_, own_t *endpoint_, pipe_t *pipe); - - // Map of open endpoints. - typedef std::pair <own_t *, pipe_t*> endpoint_pipe_t; - typedef std::multimap <std::string, endpoint_pipe_t> endpoints_t; - endpoints_t endpoints; - - // Map of open inproc endpoints. - typedef std::multimap <std::string, pipe_t *> inprocs_t; - inprocs_t inprocs; - - // To be called after processing commands or invoking any command - // handlers explicitly. If required, it will deallocate the socket. - void check_destroy (); - - // Moves the flags from the message to local variables, - // to be later retrieved by getsockopt. - void extract_flags (msg_t *msg_); - - // Used to check whether the object is a socket. - uint32_t tag; - - // If true, associated context was already terminated. - bool ctx_terminated; - - // If true, object should have been already destroyed. However, - // destruction is delayed while we unwind the stack to the point - // where it doesn't intersect the object being destroyed. - bool destroyed; - - // Parse URI string. - int parse_uri (const char *uri_, std::string &protocol_, - std::string &address_); - - // Check whether transport protocol, as specified in connect or - // bind, is available and compatible with the socket type. - int check_protocol (const std::string &protocol_); - - // Register the pipe with this socket. - void attach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_ = false); - - // Processes commands sent to this socket (if any). If timeout is -1, - // returns only after at least one command was processed. - // If throttle argument is true, commands are processed at most once - // in a predefined time period. - int process_commands (int timeout_, bool throttle_); - - // Handlers for incoming commands. - void process_stop (); - void process_bind (zmq::pipe_t *pipe_); - void process_term (int linger_); - - // Socket's mailbox object. - mailbox_t mailbox; - - // List of attached pipes. - typedef array_t <pipe_t, 3> pipes_t; - pipes_t pipes; - - // Reaper's poller and handle of this socket within it. - poller_t *poller; - poller_t::handle_t handle; - - // Timestamp of when commands were processed the last time. - uint64_t last_tsc; - - // Number of messages received since last command processing. - int ticks; - - // True if the last message received had MORE flag set. - bool rcvmore; - - // Improves efficiency of time measurement. - clock_t clock; - - // Monitor socket; - void *monitor_socket; - - // Bitmask of events being monitored - int monitor_events; - - // Last socket endpoint resolved URI - std::string last_endpoint; - - socket_base_t (const socket_base_t&); - const socket_base_t &operator = (const socket_base_t&); - mutex_t sync; - }; - -} - -#endif - diff --git a/src/stdint.hpp b/src/stdint.hpp deleted file mode 100644 index 60c29c6..0000000 --- a/src/stdint.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_STDINT_HPP_INCLUDED__ -#define __ZMQ_STDINT_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS - -#include <inttypes.h> - -#elif defined _MSC_VER && _MSC_VER < 1600 - -#ifndef int8_t -typedef __int8 int8_t; -#endif -#ifndef int16_t -typedef __int16 int16_t; -#endif -#ifndef int32_t -typedef __int32 int32_t; -#endif -#ifndef int64_t -typedef __int64 int64_t; -#endif -#ifndef uint8_t -typedef unsigned __int8 uint8_t; -#endif -#ifndef uint16_t -typedef unsigned __int16 uint16_t; -#endif -#ifndef uint32_t -typedef unsigned __int32 uint32_t; -#endif -#ifndef uint64_t -typedef unsigned __int64 uint64_t; -#endif - -#else - -#include <stdint.h> - -#endif - -#endif diff --git a/src/stream.cpp b/src/stream.cpp deleted file mode 100644 index 0b495a5..0000000 --- a/src/stream.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "stream.hpp" -#include "pipe.hpp" -#include "wire.hpp" -#include "random.hpp" -#include "likely.hpp" -#include "err.hpp" - -zmq::stream_t::stream_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - prefetched (false), - identity_sent (false), - current_out (NULL), - more_out (false), - next_peer_id (generate_random ()) -{ - options.type = ZMQ_STREAM; - options.raw_sock = true; - - prefetched_id.init (); - prefetched_msg.init (); -} - -zmq::stream_t::~stream_t () -{ - zmq_assert (outpipes.empty ()); - prefetched_id.close (); - prefetched_msg.close (); -} - -void zmq::stream_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void)subscribe_to_all_; - - zmq_assert (pipe_); - - identify_peer (pipe_); - fq.attach (pipe_); -} - -void zmq::stream_t::xpipe_terminated (pipe_t *pipe_) -{ - outpipes_t::iterator it = outpipes.find (pipe_->get_identity ()); - zmq_assert (it != outpipes.end ()); - outpipes.erase (it); - fq.pipe_terminated (pipe_); - if (pipe_ == current_out) - current_out = NULL; -} - -void zmq::stream_t::xread_activated (pipe_t *pipe_) -{ - fq.activated (pipe_); -} - -void zmq::stream_t::xwrite_activated (pipe_t *pipe_) -{ - outpipes_t::iterator it; - for (it = outpipes.begin (); it != outpipes.end (); ++it) - if (it->second.pipe == pipe_) - break; - - zmq_assert (it != outpipes.end ()); - zmq_assert (!it->second.active); - it->second.active = true; -} - -int zmq::stream_t::xsend (msg_t *msg_) -{ - // If this is the first part of the message it's the ID of the - // peer to send the message to. - if (!more_out) { - zmq_assert (!current_out); - - // If we have malformed message (prefix with no subsequent message) - // then just silently ignore it. - // TODO: The connections should be killed instead. - if (msg_->flags () & msg_t::more) { - - // Find the pipe associated with the identity stored in the prefix. - // If there's no such pipe return an error - blob_t identity ((unsigned char*) msg_->data (), msg_->size ()); - outpipes_t::iterator it = outpipes.find (identity); - - if (it != outpipes.end ()) { - current_out = it->second.pipe; - if (!current_out->check_write ()) { - it->second.active = false; - current_out = NULL; - errno = EAGAIN; - return -1; - } - } - else { - errno = EHOSTUNREACH; - return -1; - } - } - - // Expect one more message frame. - more_out = true; - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - return 0; - } - - // Ignore the MORE flag - msg_->reset_flags (msg_t::more); - - // This is the last part of the message. - more_out = false; - - // Push the message into the pipe. If there's no out pipe, just drop it. - if (current_out) { - - // 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 (msg_->size () == 0) { - current_out->terminate (false); - int rc = msg_->close (); - errno_assert (rc == 0); - current_out = NULL; - return 0; - } - bool ok = current_out->write (msg_); - if (likely (ok)) - current_out->flush (); - current_out = NULL; - } - else { - int rc = msg_->close (); - errno_assert (rc == 0); - } - - // Detach the message from the data buffer. - int rc = msg_->init (); - errno_assert (rc == 0); - - return 0; -} - -int zmq::stream_t::xrecv (msg_t *msg_) -{ - if (prefetched) { - if (!identity_sent) { - int rc = msg_->move (prefetched_id); - errno_assert (rc == 0); - identity_sent = true; - } - else { - int rc = msg_->move (prefetched_msg); - errno_assert (rc == 0); - prefetched = false; - } - return 0; - } - - pipe_t *pipe = NULL; - int rc = fq.recvpipe (&prefetched_msg, &pipe); - if (rc != 0) - return -1; - - zmq_assert (pipe != NULL); - zmq_assert ((prefetched_msg.flags () & msg_t::more) == 0); - - // We have received a frame with TCP data. - // Rather than sendig this frame, we keep it in prefetched - // buffer and send a frame with peer's ID. - blob_t identity = pipe->get_identity (); - rc = msg_->init_size (identity.size ()); - errno_assert (rc == 0); - memcpy (msg_->data (), identity.data (), identity.size ()); - msg_->set_flags (msg_t::more); - - prefetched = true; - identity_sent = true; - - return 0; -} - -bool zmq::stream_t::xhas_in () -{ - // We may already have a message pre-fetched. - if (prefetched) - return true; - - // Try to read the next message. - // The message, if read, is kept in the pre-fetch buffer. - pipe_t *pipe = NULL; - int rc = fq.recvpipe (&prefetched_msg, &pipe); - if (rc != 0) - return false; - - zmq_assert (pipe != NULL); - zmq_assert ((prefetched_msg.flags () & msg_t::more) == 0); - - blob_t identity = pipe->get_identity (); - rc = prefetched_id.init_size (identity.size ()); - errno_assert (rc == 0); - memcpy (prefetched_id.data (), identity.data (), identity.size ()); - prefetched_id.set_flags (msg_t::more); - - prefetched = true; - identity_sent = false; - - return true; -} - -bool zmq::stream_t::xhas_out () -{ - // In theory, STREAM socket is always ready for writing. Whether actual - // attempt to write succeeds depends on which pipe the message is going - // to be routed to. - return true; -} - -void zmq::stream_t::identify_peer (pipe_t *pipe_) -{ - // Always assign identity for raw-socket - unsigned char buffer [5]; - buffer [0] = 0; - put_uint32 (buffer + 1, next_peer_id++); - blob_t identity = blob_t (buffer, sizeof buffer); - - memcpy (options.identity, identity.data (), identity.size ()); - options.identity_size = identity.size (); - - pipe_->set_identity (identity); - // Add the record into output pipes lookup table - outpipe_t outpipe = {pipe_, true}; - const bool ok = outpipes.insert ( - outpipes_t::value_type (identity, outpipe)).second; - zmq_assert (ok); -} diff --git a/src/stream.hpp b/src/stream.hpp deleted file mode 100644 index 4117193..0000000 --- a/src/stream.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_STREAM_HPP_INCLUDED__ -#define __ZMQ_STREAM_HPP_INCLUDED__ - -#include <map> - -#include "router.hpp" - -namespace zmq -{ - - class ctx_t; - class pipe_t; - - class stream_t : - public socket_base_t - { - public: - - stream_t (zmq::ctx_t *parent_, uint32_t tid_, int sid); - ~stream_t (); - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsend (zmq::msg_t *msg_); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - bool xhas_out (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - // Generate peer's id and update lookup map - void identify_peer (pipe_t *pipe_); - - // Fair queueing object for inbound pipes. - fq_t fq; - - // True iff there is a message held in the pre-fetch buffer. - bool prefetched; - - // If true, the receiver got the message part with - // the peer's identity. - bool identity_sent; - - // Holds the prefetched identity. - msg_t prefetched_id; - - // Holds the prefetched message. - msg_t prefetched_msg; - - struct outpipe_t - { - zmq::pipe_t *pipe; - bool active; - }; - - // Outbound pipes indexed by the peer IDs. - typedef std::map <blob_t, outpipe_t> outpipes_t; - outpipes_t outpipes; - - // The pipe we are currently writing to. - zmq::pipe_t *current_out; - - // If true, more outgoing message parts are expected. - bool more_out; - - // Peer ID are generated. It's a simple increment and wrap-over - // algorithm. This value is the next ID to use (if not used already). - uint32_t next_peer_id; - - stream_t (const stream_t&); - const stream_t &operator = (const stream_t&); - }; - -} - -#endif diff --git a/src/stream_engine.cpp b/src/stream_engine.cpp deleted file mode 100644 index 00a1bea..0000000 --- a/src/stream_engine.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netinet/in.h> -#include <netdb.h> -#include <fcntl.h> -#endif - -#include <string.h> -#include <new> - -#include "stream_engine.hpp" -#include "io_thread.hpp" -#include "session_base.hpp" -#include "v1_encoder.hpp" -#include "v1_decoder.hpp" -#include "v2_encoder.hpp" -#include "v2_decoder.hpp" -#include "null_mechanism.hpp" -#include "plain_mechanism.hpp" -#include "curve_client.hpp" -#include "curve_server.hpp" -#include "raw_decoder.hpp" -#include "raw_encoder.hpp" -#include "config.hpp" -#include "err.hpp" -#include "ip.hpp" -#include "likely.hpp" -#include "wire.hpp" - -zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_, - const std::string &endpoint_) : - s (fd_), - inpos (NULL), - insize (0), - decoder (NULL), - outpos (NULL), - outsize (0), - encoder (NULL), - handshaking (true), - greeting_size (v2_greeting_size), - greeting_bytes_read (0), - session (NULL), - options (options_), - endpoint (endpoint_), - plugged (false), - read_msg (&stream_engine_t::read_identity), - write_msg (&stream_engine_t::write_identity), - io_error (false), - subscription_required (false), - mechanism (NULL), - input_stopped (false), - output_stopped (false), - socket (NULL) -{ - int rc = tx_msg.init (); - errno_assert (rc == 0); - - // Put the socket into non-blocking mode. - unblock_socket (s); - - if (!get_peer_ip_address (s, peer_address)) - peer_address = ""; - -#ifdef SO_NOSIGPIPE - // Make sure that SIGPIPE signal is not generated when writing to a - // connection that was already closed by the peer. - int set = 1; - rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int)); - errno_assert (rc == 0); -#endif -} - -zmq::stream_engine_t::~stream_engine_t () -{ - zmq_assert (!plugged); - - if (s != retired_fd) { -#ifdef ZMQ_HAVE_WINDOWS - int rc = closesocket (s); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = close (s); - errno_assert (rc == 0); -#endif - s = retired_fd; - } - - int rc = tx_msg.close (); - errno_assert (rc == 0); - - delete encoder; - delete decoder; - delete mechanism; -} - -void zmq::stream_engine_t::plug (io_thread_t *io_thread_, - session_base_t *session_) -{ - zmq_assert (!plugged); - plugged = true; - - // Connect to session object. - zmq_assert (!session); - zmq_assert (session_); - session = session_; - socket = session-> get_socket (); - - // Connect to I/O threads poller object. - io_object_t::plug (io_thread_); - handle = add_fd (s); - io_error = false; - - if (options.raw_sock) { - // no handshaking for raw sock, instantiate raw encoder and decoders - encoder = new (std::nothrow) raw_encoder_t (out_batch_size); - alloc_assert (encoder); - - decoder = new (std::nothrow) raw_decoder_t (in_batch_size); - alloc_assert (decoder); - - // disable handshaking for raw socket - handshaking = false; - - read_msg = &stream_engine_t::pull_msg_from_session; - write_msg = &stream_engine_t::push_msg_to_session; - } - else { - // Send the 'length' and 'flags' fields of the identity message. - // The 'length' field is encoded in the long format. - outpos = greeting_send; - outpos [outsize++] = 0xff; - put_uint64 (&outpos [outsize], options.identity_size + 1); - outsize += 8; - outpos [outsize++] = 0x7f; - } - - set_pollin (handle); - set_pollout (handle); - // Flush all the data that may have been already received downstream. - in_event (); -} - -void zmq::stream_engine_t::unplug () -{ - zmq_assert (plugged); - plugged = false; - - // Cancel all fd subscriptions. - if (!io_error) - rm_fd (handle); - - // Disconnect from I/O threads poller object. - io_object_t::unplug (); - - session = NULL; -} - -void zmq::stream_engine_t::terminate () -{ - unplug (); - delete this; -} - -void zmq::stream_engine_t::in_event () -{ - assert (!io_error); - - // If still handshaking, receive and process the greeting message. - if (unlikely (handshaking)) - if (!handshake ()) - return; - - zmq_assert (decoder); - - // If there has been an I/O error, stop polling. - if (input_stopped) { - rm_fd (handle); - io_error = true; - return; - } - - // If there's no data to process in the buffer... - if (!insize) { - - // Retrieve the buffer and read as much data as possible. - // Note that buffer can be arbitrarily large. However, we assume - // the underlying TCP layer has fixed buffer size and thus the - // number of bytes read will be always limited. - size_t bufsize = 0; - decoder->get_buffer (&inpos, &bufsize); - - int const rc = read (inpos, bufsize); - if (rc == 0) { - error (); - return; - } - if (rc == -1) { - if (errno != EAGAIN) - error (); - return; - } - - // Adjust input size - insize = static_cast <size_t> (rc); - } - - int rc = 0; - size_t processed = 0; - - while (insize > 0) { - rc = decoder->decode (inpos, insize, processed); - zmq_assert (processed <= insize); - inpos += processed; - insize -= processed; - if (rc == 0 || rc == -1) - break; - rc = (this->*write_msg) (decoder->msg ()); - if (rc == -1) - break; - } - - // Tear down the connection if we have failed to decode input data - // or the session has rejected the message. - if (rc == -1) { - if (errno != EAGAIN) { - error (); - return; - } - input_stopped = true; - reset_pollin (handle); - } - - session->flush (); -} - -void zmq::stream_engine_t::out_event () -{ - zmq_assert (!io_error); - - // If write buffer is empty, try to read new data from the encoder. - if (!outsize) { - - // Even when we stop polling as soon as there is no - // data to send, the poller may invoke out_event one - // more time due to 'speculative write' optimisation. - if (unlikely (encoder == NULL)) { - zmq_assert (handshaking); - return; - } - - outpos = NULL; - outsize = encoder->encode (&outpos, 0); - - while (outsize < out_batch_size) { - if ((this->*read_msg) (&tx_msg) == -1) - break; - encoder->load_msg (&tx_msg); - unsigned char *bufptr = outpos + outsize; - size_t n = encoder->encode (&bufptr, out_batch_size - outsize); - zmq_assert (n > 0); - if (outpos == NULL) - outpos = bufptr; - outsize += n; - } - - // If there is no data to send, stop polling for output. - if (outsize == 0) { - output_stopped = true; - reset_pollout (handle); - return; - } - } - - // If there are any data to write in write buffer, write as much as - // possible to the socket. Note that amount of data to write can be - // arbitrarily large. However, we assume that underlying TCP layer has - // limited transmission buffer and thus the actual number of bytes - // written should be reasonably modest. - int nbytes = write (outpos, outsize); - - // IO error has occurred. We stop waiting for output events. - // The engine is not terminated until we detect input error; - // this is necessary to prevent losing incoming messages. - if (nbytes == -1) { - reset_pollout (handle); - return; - } - - outpos += nbytes; - outsize -= nbytes; - - // If we are still handshaking and there are no data - // to send, stop polling for output. - if (unlikely (handshaking)) - if (outsize == 0) - reset_pollout (handle); -} - -void zmq::stream_engine_t::restart_output () -{ - if (unlikely (io_error)) - return; - - if (likely (output_stopped)) { - set_pollout (handle); - output_stopped = false; - } - - // Speculative write: The assumption is that at the moment new message - // was sent by the user the socket is probably available for writing. - // Thus we try to write the data to socket avoiding polling for POLLOUT. - // Consequently, the latency should be better in request/reply scenarios. - out_event (); -} - -void zmq::stream_engine_t::restart_input () -{ - zmq_assert (input_stopped); - zmq_assert (session != NULL); - zmq_assert (decoder != NULL); - - int rc = (this->*write_msg) (decoder->msg ()); - if (rc == -1) { - if (errno == EAGAIN) - session->flush (); - else - error (); - return; - } - - while (insize > 0) { - size_t processed = 0; - rc = decoder->decode (inpos, insize, processed); - zmq_assert (processed <= insize); - inpos += processed; - insize -= processed; - if (rc == 0 || rc == -1) - break; - rc = (this->*write_msg) (decoder->msg ()); - if (rc == -1) - break; - } - - if (rc == -1 && errno == EAGAIN) - session->flush (); - else - if (rc == -1 || io_error) - error (); - else { - input_stopped = false; - set_pollin (handle); - session->flush (); - - // Speculative read. - in_event (); - } -} - -bool zmq::stream_engine_t::handshake () -{ - zmq_assert (handshaking); - zmq_assert (greeting_bytes_read < greeting_size); - // Receive the greeting. - while (greeting_bytes_read < greeting_size) { - const int n = read (greeting_recv + greeting_bytes_read, - greeting_size - greeting_bytes_read); - if (n == 0) { - error (); - return false; - } - if (n == -1) { - if (errno != EAGAIN) - error (); - return false; - } - - greeting_bytes_read += n; - - // We have received at least one byte from the peer. - // If the first byte is not 0xff, we know that the - // peer is using unversioned protocol. - if (greeting_recv [0] != 0xff) - break; - - if (greeting_bytes_read < signature_size) - continue; - - // Inspect the right-most bit of the 10th byte (which coincides - // with the 'flags' field if a regular message was sent). - // Zero indicates this is a header of identity message - // (i.e. the peer is using the unversioned protocol). - if (!(greeting_recv [9] & 0x01)) - break; - - // The peer is using versioned protocol. - // Send the major version number. - if (outpos + outsize == greeting_send + signature_size) { - if (outsize == 0) - set_pollout (handle); - outpos [outsize++] = 3; // Major version number - } - - if (greeting_bytes_read > signature_size) { - if (outpos + outsize == greeting_send + signature_size + 1) { - if (outsize == 0) - set_pollout (handle); - - // Use ZMTP/2.0 to talk to older peers. - if (greeting_recv [10] == ZMTP_1_0 - || greeting_recv [10] == ZMTP_2_0) - outpos [outsize++] = options.type; - else { - outpos [outsize++] = 0; // Minor version number - memset (outpos + outsize, 0, 20); - - zmq_assert (options.mechanism == ZMQ_NULL - || options.mechanism == ZMQ_PLAIN - || options.mechanism == ZMQ_CURVE); - - if (options.mechanism == ZMQ_NULL) - memcpy (outpos + outsize, "NULL", 4); - else - if (options.mechanism == ZMQ_PLAIN) - memcpy (outpos + outsize, "PLAIN", 5); - else - memcpy (outpos + outsize, "CURVE", 5); - outsize += 20; - memset (outpos + outsize, 0, 32); - outsize += 32; - greeting_size = v3_greeting_size; - } - } - } - } - - // Position of the revision field in the greeting. - const size_t revision_pos = 10; - - // Is the peer using ZMTP/1.0 with no revision number? - // If so, we send and receive rest of identity message - if (greeting_recv [0] != 0xff || !(greeting_recv [9] & 0x01)) { - encoder = new (std::nothrow) v1_encoder_t (out_batch_size); - alloc_assert (encoder); - - decoder = new (std::nothrow) v1_decoder_t (in_batch_size, options.maxmsgsize); - alloc_assert (decoder); - - // We have already sent the message header. - // Since there is no way to tell the encoder to - // skip the message header, we simply throw that - // header data away. - const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2; - unsigned char tmp [10], *bufferp = tmp; - - // Prepare the identity message and load it into encoder. - // Then consume bytes we have already sent to the peer. - const int rc = tx_msg.init_size (options.identity_size); - zmq_assert (rc == 0); - memcpy (tx_msg.data (), options.identity, options.identity_size); - encoder->load_msg (&tx_msg); - size_t buffer_size = encoder->encode (&bufferp, header_size); - zmq_assert (buffer_size == header_size); - - // Make sure the decoder sees the data we have already received. - inpos = greeting_recv; - insize = greeting_bytes_read; - - // To allow for interoperability with peers that do not forward - // their subscriptions, we inject a phantom subscription message - // message into the incoming message stream. - if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB) - subscription_required = true; - - // We are sending our identity now and the next message - // will come from the socket. - read_msg = &stream_engine_t::pull_msg_from_session; - - // We are expecting identity message. - write_msg = &stream_engine_t::write_identity; - } - else - if (greeting_recv [revision_pos] == ZMTP_1_0) { - encoder = new (std::nothrow) v1_encoder_t ( - out_batch_size); - alloc_assert (encoder); - - decoder = new (std::nothrow) v1_decoder_t ( - in_batch_size, options.maxmsgsize); - alloc_assert (decoder); - } - else - if (greeting_recv [revision_pos] == ZMTP_2_0) { - encoder = new (std::nothrow) v2_encoder_t (out_batch_size); - alloc_assert (encoder); - - decoder = new (std::nothrow) v2_decoder_t ( - in_batch_size, options.maxmsgsize); - alloc_assert (decoder); - } - else { - encoder = new (std::nothrow) v2_encoder_t (out_batch_size); - alloc_assert (encoder); - - decoder = new (std::nothrow) v2_decoder_t ( - in_batch_size, options.maxmsgsize); - alloc_assert (decoder); - - if (memcmp (greeting_recv + 12, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) { - mechanism = new (std::nothrow) - null_mechanism_t (session, peer_address, options); - alloc_assert (mechanism); - } - else - if (memcmp (greeting_recv + 12, "PLAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) { - mechanism = new (std::nothrow) - plain_mechanism_t (session, peer_address, options); - alloc_assert (mechanism); - } -#ifdef HAVE_LIBSODIUM - else - if (memcmp (greeting_recv + 12, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) { - if (options.as_server) - mechanism = new (std::nothrow) - curve_server_t (session, peer_address, options); - else - mechanism = new (std::nothrow) curve_client_t (options); - alloc_assert (mechanism); - } -#endif - else { - error (); - return false; - } - read_msg = &stream_engine_t::next_handshake_command; - write_msg = &stream_engine_t::process_handshake_command; - } - - // Start polling for output if necessary. - if (outsize == 0) - set_pollout (handle); - - // Handshaking was successful. - // Switch into the normal message flow. - handshaking = false; - - return true; -} - -int zmq::stream_engine_t::read_identity (msg_t *msg_) -{ - int rc = msg_->init_size (options.identity_size); - errno_assert (rc == 0); - if (options.identity_size > 0) - memcpy (msg_->data (), options.identity, options.identity_size); - read_msg = &stream_engine_t::pull_msg_from_session; - return 0; -} - -int zmq::stream_engine_t::write_identity (msg_t *msg_) -{ - if (options.recv_identity) { - msg_->set_flags (msg_t::identity); - int rc = session->push_msg (msg_); - errno_assert (rc == 0); - } - else { - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - } - - if (subscription_required) - write_msg = &stream_engine_t::write_subscription_msg; - else - write_msg = &stream_engine_t::push_msg_to_session; - - return 0; -} - -int zmq::stream_engine_t::next_handshake_command (msg_t *msg_) -{ - zmq_assert (mechanism != NULL); - - const int rc = mechanism->next_handshake_command (msg_); - if (rc == 0) { - msg_->set_flags (msg_t::command); - if (mechanism->is_handshake_complete ()) - mechanism_ready (); - } - - return rc; -} - -int zmq::stream_engine_t::process_handshake_command (msg_t *msg_) -{ - zmq_assert (mechanism != NULL); - const int rc = mechanism->process_handshake_command (msg_); - if (rc == 0) { - if (mechanism->is_handshake_complete ()) - mechanism_ready (); - if (output_stopped) - restart_output (); - } - - return rc; -} - -void zmq::stream_engine_t::zap_msg_available () -{ - zmq_assert (mechanism != NULL); - - const int rc = mechanism->zap_msg_available (); - if (rc == -1) { - error (); - return; - } - if (input_stopped) - restart_input (); - if (output_stopped) - restart_output (); -} - -void zmq::stream_engine_t::mechanism_ready () -{ - if (options.recv_identity) { - msg_t identity; - mechanism->peer_identity (&identity); - const int rc = session->push_msg (&identity); - if (rc == -1 && errno == EAGAIN) { - // If the write is failing at this stage with - // an EAGAIN the pipe must be being shut down, - // so we can just bail out of the identity set. - return; - } - errno_assert (rc == 0); - session->flush (); - } - - read_msg = &stream_engine_t::pull_and_encode; - write_msg = &stream_engine_t::decode_and_push; -} - -int zmq::stream_engine_t::pull_msg_from_session (msg_t *msg_) -{ - return session->pull_msg (msg_); -} - -int zmq::stream_engine_t::push_msg_to_session (msg_t *msg_) -{ - return session->push_msg (msg_); -} - -int zmq::stream_engine_t::pull_and_encode (msg_t *msg_) -{ - zmq_assert (mechanism != NULL); - - if (session->pull_msg (msg_) == -1) - return -1; - if (mechanism->encode (msg_) == -1) - return -1; - return 0; -} - -int zmq::stream_engine_t::decode_and_push (msg_t *msg_) -{ - zmq_assert (mechanism != NULL); - - if (mechanism->decode (msg_) == -1) - return -1; - if (session->push_msg (msg_) == -1) { - if (errno == EAGAIN) - write_msg = &stream_engine_t::push_one_then_decode_and_push; - return -1; - } - return 0; -} - -int zmq::stream_engine_t::push_one_then_decode_and_push (msg_t *msg_) -{ - const int rc = session->push_msg (msg_); - if (rc == 0) - write_msg = &stream_engine_t::decode_and_push; - return rc; -} - -int zmq::stream_engine_t::write_subscription_msg (msg_t *msg_) -{ - msg_t subscription; - - // Inject the subscription message, so that also - // ZMQ 2.x peers receive published messages. - int rc = subscription.init_size (1); - errno_assert (rc == 0); - *(unsigned char*) subscription.data () = 1; - rc = session->push_msg (&subscription); - if (rc == -1) - return -1; - - write_msg = &stream_engine_t::push_msg_to_session; - return push_msg_to_session (msg_); -} - -void zmq::stream_engine_t::error () -{ - zmq_assert (session); - socket->event_disconnected (endpoint, s); - session->flush (); - session->detach (); - unplug (); - delete this; -} - -int zmq::stream_engine_t::write (const void *data_, size_t size_) -{ -#ifdef ZMQ_HAVE_WINDOWS - - int nbytes = send (s, (char*) data_, (int) size_, 0); - - // If not a single byte can be written to the socket in non-blocking mode - // we'll get an error (this may happen during the speculative write). - if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) - return 0; - - // Signalise peer failure. - if (nbytes == SOCKET_ERROR && ( - WSAGetLastError () == WSAENETDOWN || - WSAGetLastError () == WSAENETRESET || - WSAGetLastError () == WSAEHOSTUNREACH || - WSAGetLastError () == WSAECONNABORTED || - WSAGetLastError () == WSAETIMEDOUT || - WSAGetLastError () == WSAECONNRESET)) - return -1; - - wsa_assert (nbytes != SOCKET_ERROR); - return nbytes; - -#else - - ssize_t nbytes = send (s, data_, size_, 0); - - // Several errors are OK. When speculative write is being done we may not - // be able to write a single byte from the socket. Also, SIGSTOP issued - // by a debugging tool can result in EINTR error. - if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINTR)) - return 0; - - // Signalise peer failure. - if (nbytes == -1) { - errno_assert (errno != EACCES - && errno != EBADF - && errno != EDESTADDRREQ - && errno != EFAULT - && errno != EINVAL - && errno != EISCONN - && errno != EMSGSIZE - && errno != ENOMEM - && errno != ENOTSOCK - && errno != EOPNOTSUPP); - return -1; - } - - return static_cast <int> (nbytes); - -#endif -} - -int zmq::stream_engine_t::read (void *data_, size_t size_) -{ -#ifdef ZMQ_HAVE_WINDOWS - - const int rc = recv (s, (char*) data_, (int) size_, 0); - - // If not a single byte can be read from the socket in non-blocking mode - // we'll get an error (this may happen during the speculative read). - if (rc == SOCKET_ERROR) { - if (WSAGetLastError () == WSAEWOULDBLOCK) - errno = EAGAIN; - else { - wsa_assert (WSAGetLastError () == WSAENETDOWN - || WSAGetLastError () == WSAENETRESET - || WSAGetLastError () == WSAECONNABORTED - || WSAGetLastError () == WSAETIMEDOUT - || WSAGetLastError () == WSAECONNRESET - || WSAGetLastError () == WSAECONNREFUSED - || WSAGetLastError () == WSAENOTCONN); - errno = wsa_error_to_errno (WSAGetLastError ()); - } - } - - return rc == SOCKET_ERROR? -1: rc; - -#else - - const ssize_t rc = recv (s, data_, size_, 0); - - // Several errors are OK. When speculative read is being done we may not - // be able to read a single byte from the socket. Also, SIGSTOP issued - // by a debugging tool can result in EINTR error. - if (rc == -1) { - errno_assert (errno != EBADF - && errno != EFAULT - && errno != EINVAL - && errno != ENOMEM - && errno != ENOTSOCK); - if (errno == EWOULDBLOCK || errno == EINTR) - errno = EAGAIN; - } - - return static_cast <int> (rc); - -#endif -} diff --git a/src/stream_engine.hpp b/src/stream_engine.hpp deleted file mode 100644 index 631d1cb..0000000 --- a/src/stream_engine.hpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_STREAM_ENGINE_HPP_INCLUDED__ -#define __ZMQ_STREAM_ENGINE_HPP_INCLUDED__ - -#include <stddef.h> - -#include "fd.hpp" -#include "i_engine.hpp" -#include "io_object.hpp" -#include "i_encoder.hpp" -#include "i_decoder.hpp" -#include "options.hpp" -#include "socket_base.hpp" -#include "../include/zmq.h" - -namespace zmq -{ - // Protocol revisions - enum - { - ZMTP_1_0 = 0, - ZMTP_2_0 = 1 - }; - - class io_thread_t; - class msg_t; - class session_base_t; - class mechanism_t; - - // This engine handles any socket with SOCK_STREAM semantics, - // e.g. TCP socket or an UNIX domain socket. - - class stream_engine_t : public io_object_t, public i_engine - { - public: - - stream_engine_t (fd_t fd_, const options_t &options_, - const std::string &endpoint); - ~stream_engine_t (); - - // i_engine interface implementation. - void plug (zmq::io_thread_t *io_thread_, - zmq::session_base_t *session_); - void terminate (); - void restart_input (); - void restart_output (); - void zap_msg_available (); - - // i_poll_events interface implementation. - void in_event (); - void out_event (); - - private: - - // Unplug the engine from the session. - void unplug (); - - // Function to handle network disconnections. - void error (); - - // Receives the greeting message from the peer. - int receive_greeting (); - - // Detects the protocol used by the peer. - bool handshake (); - - // Writes data to the socket. Returns the number of bytes actually - // written (even zero is to be considered to be a success). In case - // of error or orderly shutdown by the other peer -1 is returned. - int write (const void *data_, size_t size_); - - // Reads data from the socket (up to 'size' bytes). - // Returns the number of bytes actually read or -1 on error. - // Zero indicates the peer has closed the connection. - int read (void *data_, size_t size_); - - int read_identity (msg_t *msg_); - int write_identity (msg_t *msg_); - - int next_handshake_command (msg_t *msg); - int process_handshake_command (msg_t *msg); - - int pull_msg_from_session (msg_t *msg_); - int push_msg_to_session (msg_t *msg); - - int pull_and_encode (msg_t *msg_); - int decode_and_push (msg_t *msg_); - int push_one_then_decode_and_push (msg_t *msg_); - - void mechanism_ready (); - - int write_subscription_msg (msg_t *msg_); - - size_t add_property (unsigned char *ptr, - const char *name, const void *value, size_t value_len); - - // Underlying socket. - fd_t s; - - // True iff this is server's engine. - bool as_server; - - msg_t tx_msg; - - handle_t handle; - - unsigned char *inpos; - size_t insize; - i_decoder *decoder; - - unsigned char *outpos; - size_t outsize; - i_encoder *encoder; - - // When true, we are still trying to determine whether - // the peer is using versioned protocol, and if so, which - // version. When false, normal message flow has started. - bool handshaking; - - static const size_t signature_size = 10; - - // Size of ZMTP/1.0 and ZMTP/2.0 greeting message - static const size_t v2_greeting_size = 12; - - // Size of ZMTP/3.0 greeting message - static const size_t v3_greeting_size = 64; - - // Expected greeting size. - size_t greeting_size; - - // Greeting received from, and sent to peer - unsigned char greeting_recv [v3_greeting_size]; - unsigned char greeting_send [v3_greeting_size]; - - // Size of greeting received so far - unsigned int greeting_bytes_read; - - // The session this engine is attached to. - zmq::session_base_t *session; - - options_t options; - - // String representation of endpoint - std::string endpoint; - - bool plugged; - - int (stream_engine_t::*read_msg) (msg_t *msg_); - - int (stream_engine_t::*write_msg) (msg_t *msg_); - - bool io_error; - - // Indicates whether the engine is to inject a phantom - // subscription message into the incoming stream. - // Needed to support old peers. - bool subscription_required; - - mechanism_t *mechanism; - - // True iff the engine couldn't consume the last decoded message. - bool input_stopped; - - // True iff the engine doesn't have any message to encode. - bool output_stopped; - - // Socket - zmq::socket_base_t *socket; - - std::string peer_address; - - stream_engine_t (const stream_engine_t&); - const stream_engine_t &operator = (const stream_engine_t&); - }; - -} - -#endif diff --git a/src/sub.cpp b/src/sub.cpp deleted file mode 100644 index 6edb7bb..0000000 --- a/src/sub.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "sub.hpp" -#include "msg.hpp" - -zmq::sub_t::sub_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - xsub_t (parent_, tid_, sid_) -{ - options.type = ZMQ_SUB; - - // Switch filtering messages on (as opposed to XSUB which where the - // filtering is off). - options.filter = true; -} - -zmq::sub_t::~sub_t () -{ -} - -int zmq::sub_t::xsetsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - if (option_ != ZMQ_SUBSCRIBE && option_ != ZMQ_UNSUBSCRIBE) { - errno = EINVAL; - return -1; - } - - // Create the subscription message. - msg_t msg; - int rc = msg.init_size (optvallen_ + 1); - errno_assert (rc == 0); - unsigned char *data = (unsigned char*) msg.data (); - if (option_ == ZMQ_SUBSCRIBE) - *data = 1; - else - if (option_ == ZMQ_UNSUBSCRIBE) - *data = 0; - memcpy (data + 1, optval_, optvallen_); - - // Pass it further on in the stack. - int err = 0; - rc = xsub_t::xsend (&msg); - if (rc != 0) - err = errno; - int rc2 = msg.close (); - errno_assert (rc2 == 0); - if (rc != 0) - errno = err; - return rc; -} - -int zmq::sub_t::xsend (msg_t *) -{ - // Overload the XSUB's send. - errno = ENOTSUP; - return -1; -} - -bool zmq::sub_t::xhas_out () -{ - // Overload the XSUB's send. - return false; -} diff --git a/src/sub.hpp b/src/sub.hpp deleted file mode 100644 index 0a4df73..0000000 --- a/src/sub.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_SUB_HPP_INCLUDED__ -#define __ZMQ_SUB_HPP_INCLUDED__ - -#include "xsub.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class io_thread_t; - class socket_base_t; - - class sub_t : public xsub_t - { - public: - - sub_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~sub_t (); - - protected: - - int xsetsockopt (int option_, const void *optval_, size_t optvallen_); - int xsend (zmq::msg_t *msg_); - bool xhas_out (); - - private: - - sub_t (const sub_t&); - const sub_t &operator = (const sub_t&); - }; - -} - -#endif diff --git a/src/tcp.cpp b/src/tcp.cpp deleted file mode 100755 index b33cbef..0000000 --- a/src/tcp.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ip.hpp" -#include "tcp.hpp" -#include "err.hpp" -#include "platform.hpp" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#endif - -#if defined ZMQ_HAVE_OPENVMS -#include <ioctl.h> -#endif - -void zmq::tune_tcp_socket (fd_t s_) -{ - // Disable Nagle's algorithm. We are doing data batching on 0MQ level, - // so using Nagle wouldn't improve throughput in anyway, but it would - // hurt latency. - int nodelay = 1; - int rc = setsockopt (s_, IPPROTO_TCP, TCP_NODELAY, (char*) &nodelay, - sizeof (int)); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else - errno_assert (rc == 0); -#endif - -#ifdef ZMQ_HAVE_OPENVMS - // Disable delayed acknowledgements as they hurt latency is serious manner. - int nodelack = 1; - rc = setsockopt (s_, IPPROTO_TCP, TCP_NODELACK, (char*) &nodelack, - sizeof (int)); - errno_assert (rc != SOCKET_ERROR); -#endif -} - -void zmq::set_tcp_send_buffer (fd_t sockfd_, int bufsize_) -{ - const int rc = setsockopt (sockfd_, SOL_SOCKET, SO_SNDBUF, - (char*) &bufsize_, sizeof bufsize_); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else - errno_assert (rc == 0); -#endif -} - -void zmq::set_tcp_receive_buffer (fd_t sockfd_, int bufsize_) -{ - const int rc = setsockopt (sockfd_, SOL_SOCKET, SO_RCVBUF, - (char*) &bufsize_, sizeof bufsize_); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else - errno_assert (rc == 0); -#endif -} - -void zmq::tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int keepalive_idle_, int keepalive_intvl_) -{ - // These options are used only under certain #ifdefs below. - (void)keepalive_; - (void)keepalive_cnt_; - (void)keepalive_idle_; - (void)keepalive_intvl_; - - // If none of the #ifdefs apply, then s_ is unused. - (void)s_; - - // Tuning TCP keep-alives if platform allows it - // All values = -1 means skip and leave it for OS -#ifdef ZMQ_HAVE_WINDOWS - tcp_keepalive keepalive_opts; - keepalive_opts.onoff = keepalive_; - keepalive_opts.keepalivetime = keepalive_idle_ != -1 ? keepalive_idle_ * 1000 : 7200000; - keepalive_opts.keepaliveinterval = keepalive_intvl_ != -1 ? keepalive_intvl_ * 1000 : 1000; - DWORD num_bytes_returned; - int rc = WSAIoctl(s_, SIO_KEEPALIVE_VALS, &keepalive_opts, sizeof(keepalive_opts), NULL, 0, &num_bytes_returned, NULL, NULL); - wsa_assert (rc != SOCKET_ERROR); -#else -#ifdef ZMQ_HAVE_SO_KEEPALIVE - if (keepalive_ != -1) { - int rc = setsockopt (s_, SOL_SOCKET, SO_KEEPALIVE, (char*) &keepalive_, sizeof (int)); - errno_assert (rc == 0); - -#ifdef ZMQ_HAVE_TCP_KEEPCNT - if (keepalive_cnt_ != -1) { - int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPCNT, &keepalive_cnt_, sizeof (int)); - errno_assert (rc == 0); - } -#endif // ZMQ_HAVE_TCP_KEEPCNT - -#ifdef ZMQ_HAVE_TCP_KEEPIDLE - if (keepalive_idle_ != -1) { - int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_idle_, sizeof (int)); - errno_assert (rc == 0); - } -#else // ZMQ_HAVE_TCP_KEEPIDLE -#ifdef ZMQ_HAVE_TCP_KEEPALIVE - if (keepalive_idle_ != -1) { - int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPALIVE, &keepalive_idle_, sizeof (int)); - errno_assert (rc == 0); - } -#endif // ZMQ_HAVE_TCP_KEEPALIVE -#endif // ZMQ_HAVE_TCP_KEEPIDLE - -#ifdef ZMQ_HAVE_TCP_KEEPINTVL - if (keepalive_intvl_ != -1) { - int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl_, sizeof (int)); - errno_assert (rc == 0); - } -#endif // ZMQ_HAVE_TCP_KEEPINTVL - } -#endif // ZMQ_HAVE_SO_KEEPALIVE -#endif // ZMQ_HAVE_WINDOWS -} diff --git a/src/tcp.hpp b/src/tcp.hpp deleted file mode 100644 index 28d6af7..0000000 --- a/src/tcp.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_TCP_HPP_INCLUDED__ -#define __ZMQ_TCP_HPP_INCLUDED__ - -#include "fd.hpp" - -namespace zmq -{ - - // Tunes the supplied TCP socket for the best latency. - void tune_tcp_socket (fd_t s_); - - // Sets the socket send buffer size. - void set_tcp_send_buffer (fd_t sockfd_, int bufsize_); - - // Sets the socket receive buffer size. - void set_tcp_receive_buffer (fd_t sockfd_, int bufsize_); - - // Tunes TCP keep-alives - void tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int keepalive_idle_, int keepalive_intvl_); - -} - -#endif diff --git a/src/tcp_address.cpp b/src/tcp_address.cpp deleted file mode 100644 index 1c75812..0000000 --- a/src/tcp_address.cpp +++ /dev/null @@ -1,602 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string> -#include <sstream> - -#include "tcp_address.hpp" -#include "platform.hpp" -#include "stdint.hpp" -#include "err.hpp" -#include "ip.hpp" - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <sys/types.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netdb.h> -#endif - -// Some platforms (notably Darwin/OSX and NetBSD) do not define all AI_ -// flags for getaddrinfo(). This can be worked around safely by defining -// these to 0. -#ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 -#endif - -#if defined ZMQ_HAVE_SOLARIS - -#include <sys/sockio.h> -#include <net/if.h> -#include <unistd.h> -#include <stdlib.h> - -// On Solaris platform, network interface name can be queried by ioctl. -int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_) -{ - // TODO: Unused parameter, IPv6 support not implemented for Solaris. - (void) ipv6_; - - // Create a socket. - int fd = open_socket (AF_INET, SOCK_DGRAM, 0); - errno_assert (fd != -1); - - // Retrieve number of interfaces. - lifnum ifn; - ifn.lifn_family = AF_INET; - ifn.lifn_flags = 0; - int rc = ioctl (fd, SIOCGLIFNUM, (char*) &ifn); - errno_assert (rc != -1); - - // Allocate memory to get interface names. - size_t ifr_size = sizeof (struct lifreq) * ifn.lifn_count; - char *ifr = (char*) malloc (ifr_size); - alloc_assert (ifr); - - // Retrieve interface names. - lifconf ifc; - ifc.lifc_family = AF_INET; - ifc.lifc_flags = 0; - ifc.lifc_len = ifr_size; - ifc.lifc_buf = ifr; - rc = ioctl (fd, SIOCGLIFCONF, (char*) &ifc); - errno_assert (rc != -1); - - // Find the interface with the specified name and AF_INET family. - bool found = false; - lifreq *ifrp = ifc.lifc_req; - for (int n = 0; n < (int) (ifc.lifc_len / sizeof (lifreq)); - n ++, ifrp ++) { - if (!strcmp (nic_, ifrp->lifr_name)) { - rc = ioctl (fd, SIOCGLIFADDR, (char*) ifrp); - errno_assert (rc != -1); - if (ifrp->lifr_addr.ss_family == AF_INET) { - address.ipv4 = *(sockaddr_in*) &ifrp->lifr_addr; - found = true; - break; - } - } - } - - // Clean-up. - free (ifr); - close (fd); - - if (!found) { - errno = ENODEV; - return -1; - } - return 0; -} - -#elif defined ZMQ_HAVE_AIX || defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_ANDROID - -#include <sys/types.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <net/if.h> - -int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_) -{ - // TODO: Unused parameter, IPv6 support not implemented for AIX or HP/UX. - (void) ipv6_; - - // Create a socket. - int sd = open_socket (AF_INET, SOCK_DGRAM, 0); - errno_assert (sd != -1); - - struct ifreq ifr; - - // Copy interface name for ioctl get. - strncpy (ifr.ifr_name, nic_, sizeof (ifr.ifr_name)); - - // Fetch interface address. - int rc = ioctl (sd, SIOCGIFADDR, (caddr_t) &ifr, sizeof (struct ifreq)); - - // Clean up. - close (sd); - - if (rc == -1) { - errno = ENODEV; - return -1; - } - memcpy (&address.ipv4.sin_addr, &((sockaddr_in*) &ifr.ifr_addr)->sin_addr, - sizeof (in_addr)); - - return 0; -} - -#elif ((defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_OPENBSD ||\ - defined ZMQ_HAVE_QNXNTO || defined ZMQ_HAVE_NETBSD)\ - && defined ZMQ_HAVE_IFADDRS) - -#include <ifaddrs.h> - -// On these platforms, network interface name can be queried -// using getifaddrs function. -int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_) -{ - // Get the addresses. - ifaddrs *ifa = NULL; - int rc = getifaddrs (&ifa); - errno_assert (rc == 0); - zmq_assert (ifa != NULL); - - // Find the corresponding network interface. - bool found = false; - for (ifaddrs *ifp = ifa; ifp != NULL ;ifp = ifp->ifa_next) - { - if (ifp->ifa_addr == NULL) - continue; - - int family = ifp->ifa_addr->sa_family; - if ((family == AF_INET || (ipv6_ && family == AF_INET6)) - && !strcmp (nic_, ifp->ifa_name)) { - memcpy (&address, ifp->ifa_addr, - (family == AF_INET) ? sizeof (struct sockaddr_in) - : sizeof (struct sockaddr_in6)); - found = true; - break; - } - } - - // Clean-up; - freeifaddrs (ifa); - - if (!found) { - errno = ENODEV; - return -1; - } - return 0; -} - -#else - -// On other platforms we assume there are no sane interface names. -// This is true especially of Windows. -int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_) -{ - // All unused parameters. - (void) nic_; - (void) ipv6_; - - errno = ENODEV; - return -1; -} - -#endif - -int zmq::tcp_address_t::resolve_interface (const char *interface_, bool ipv6_) -{ - // Initialize temporary output pointers with storage address. - sockaddr_storage ss; - sockaddr *out_addr = (sockaddr*) &ss; - size_t out_addrlen; - - // Initialise IP-format family/port and populate temporary output pointers - // with the address. - if (ipv6_) { - sockaddr_in6 ip6_addr; - memset (&ip6_addr, 0, sizeof (ip6_addr)); - ip6_addr.sin6_family = AF_INET6; - memcpy (&ip6_addr.sin6_addr, &in6addr_any, sizeof (in6addr_any)); - out_addrlen = sizeof ip6_addr; - memcpy (out_addr, &ip6_addr, out_addrlen); - } - else { - sockaddr_in ip4_addr; - memset (&ip4_addr, 0, sizeof (ip4_addr)); - ip4_addr.sin_family = AF_INET; - ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY); - out_addrlen = sizeof ip4_addr; - memcpy (out_addr, &ip4_addr, out_addrlen); - } - // "*" resolves to INADDR_ANY or in6addr_any. - if (strcmp (interface_, "*") == 0) { - zmq_assert (out_addrlen <= sizeof address); - memcpy (&address, out_addr, out_addrlen); - return 0; - } - - // Try to resolve the string as a NIC name. - int rc = resolve_nic_name (interface_, ipv6_); - if (rc != 0 && errno != ENODEV) - return rc; - if (rc == 0) - return 0; - - // There's no such interface name. Assume literal address. -#if defined ZMQ_HAVE_OPENVMS && defined __ia64 - __addrinfo64 *res = NULL; - __addrinfo64 req; -#else - addrinfo *res = NULL; - addrinfo req; -#endif - memset (&req, 0, sizeof (req)); - - // Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for - // IPv4-in-IPv6 addresses. - req.ai_family = ipv6_? AF_INET6: AF_INET; - - // Arbitrary, not used in the output, but avoids duplicate results. - req.ai_socktype = SOCK_STREAM; - - // Restrict hostname/service to literals to avoid any DNS lookups or - // service-name irregularity due to indeterminate socktype. - req.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - -#if defined AI_V4MAPPED && !defined ZMQ_HAVE_FREEBSD - // In this API we only require IPv4-mapped addresses when - // no native IPv6 interfaces are available (~AI_ALL). - // This saves an additional DNS roundtrip for IPv4 addresses. - // Note: While the AI_V4MAPPED flag is defined on FreeBSD system, - // it is not supported here. See libzmq issue #331. - if (req.ai_family == AF_INET6) - req.ai_flags |= AI_V4MAPPED; -#endif - - // Resolve the literal address. Some of the error info is lost in case - // of error, however, there's no way to report EAI errors via errno. - rc = getaddrinfo (interface_, NULL, &req, &res); - if (rc) { - errno = ENODEV; - return -1; - } - - // Use the first result. - zmq_assert (res != NULL); - zmq_assert ((size_t) (res->ai_addrlen) <= sizeof (address)); - memcpy (&address, res->ai_addr, res->ai_addrlen); - - // Cleanup getaddrinfo after copying the possibly referenced result. - freeaddrinfo (res); - - return 0; -} - -int zmq::tcp_address_t::resolve_hostname (const char *hostname_, bool ipv6_) -{ - // Set up the query. -#if defined ZMQ_HAVE_OPENVMS && defined __ia64 && __INITIAL_POINTER_SIZE == 64 - __addrinfo64 req; -#else - addrinfo req; -#endif - memset (&req, 0, sizeof (req)); - - // Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for - // IPv4-in-IPv6 addresses. - req.ai_family = ipv6_? AF_INET6: AF_INET; - - // Need to choose one to avoid duplicate results from getaddrinfo() - this - // doesn't really matter, since it's not included in the addr-output. - req.ai_socktype = SOCK_STREAM; - -#if defined AI_V4MAPPED && !defined ZMQ_HAVE_FREEBSD - // In this API we only require IPv4-mapped addresses when - // no native IPv6 interfaces are available. - // This saves an additional DNS roundtrip for IPv4 addresses. - // Note: While the AI_V4MAPPED flag is defined on FreeBSD system, - // it is not supported here. See libzmq issue #331. - if (req.ai_family == AF_INET6) - req.ai_flags |= AI_V4MAPPED; -#endif - - // Resolve host name. Some of the error info is lost in case of error, - // however, there's no way to report EAI errors via errno. -#if defined ZMQ_HAVE_OPENVMS && defined __ia64 && __INITIAL_POINTER_SIZE == 64 - __addrinfo64 *res; -#else - addrinfo *res; -#endif - int rc = getaddrinfo (hostname_, NULL, &req, &res); - if (rc) { - switch (rc) { - case EAI_MEMORY: - errno = ENOMEM; - break; - default: - errno = EINVAL; - break; - } - return -1; - } - - // Copy first result to output addr with hostname and service. - zmq_assert ((size_t) (res->ai_addrlen) <= sizeof (address)); - memcpy (&address, res->ai_addr, res->ai_addrlen); - - freeaddrinfo (res); - - return 0; -} - -zmq::tcp_address_t::tcp_address_t () -{ - memset (&address, 0, sizeof (address)); -} - -zmq::tcp_address_t::tcp_address_t (const sockaddr *sa, socklen_t sa_len) -{ - zmq_assert(sa && sa_len > 0); - - memset (&address, 0, sizeof (address)); - if (sa->sa_family == AF_INET && sa_len >= (socklen_t) sizeof (address.ipv4)) - memcpy(&address.ipv4, sa, sizeof (address.ipv4)); - else - if (sa->sa_family == AF_INET6 && sa_len >= (socklen_t) sizeof (address.ipv6)) - memcpy(&address.ipv6, sa, sizeof (address.ipv6)); -} - -zmq::tcp_address_t::~tcp_address_t () -{ -} - -int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_) -{ - // Find the ':' at end that separates address from the port number. - const char *delimiter = strrchr (name_, ':'); - if (!delimiter) { - errno = EINVAL; - return -1; - } - // Separate the address/port. - std::string addr_str (name_, delimiter - name_); - std::string port_str (delimiter + 1); - - // Remove square brackets around the address, if any. - if (addr_str.size () >= 2 && addr_str [0] == '[' && - addr_str [addr_str.size () - 1] == ']') - addr_str = addr_str.substr (1, addr_str.size () - 2); - - // Allow 0 specifically, to detect invalid port error in atoi if not - uint16_t port; - if (port_str == "*" || port_str == "0") - // Resolve wildcard to 0 to allow autoselection of port - port = 0; - else { - // Parse the port number (0 is not a valid port). - port = (uint16_t) atoi (port_str.c_str ()); - if (port == 0) { - errno = EINVAL; - return -1; - } - } - - // Resolve the IP address. - int rc; - if (local_) - rc = resolve_interface (addr_str.c_str (), ipv6_); - else - rc = resolve_hostname (addr_str.c_str (), ipv6_); - if (rc != 0) - return -1; - - // Set the port into the address structure. - if (address.generic.sa_family == AF_INET6) - address.ipv6.sin6_port = htons (port); - else - address.ipv4.sin_port = htons (port); - - return 0; -} - -int zmq::tcp_address_t::to_string (std::string &addr_) -{ - if (address.generic.sa_family != AF_INET - && address.generic.sa_family != AF_INET6) { - addr_.clear (); - return -1; - } - - // not using service resolv because of https://github.com/zeromq/libzmq/commit/1824574f9b5a8ce786853320e3ea09fe1f822bc4 - char hbuf[NI_MAXHOST]; - int rc = getnameinfo (addr (), addrlen (), hbuf, sizeof (hbuf), NULL, 0, NI_NUMERICHOST); - if (rc != 0) { - addr_.clear (); - return rc; - } - - if (address.generic.sa_family == AF_INET6) { - std::stringstream s; - s << "tcp://[" << hbuf << "]:" << ntohs (address.ipv6.sin6_port); - addr_ = s.str (); - } - else { - std::stringstream s; - s << "tcp://" << hbuf << ":" << ntohs (address.ipv4.sin_port); - addr_ = s.str (); - }; - return 0; -} - -const sockaddr *zmq::tcp_address_t::addr () const -{ - return &address.generic; -} - -socklen_t zmq::tcp_address_t::addrlen () const -{ - if (address.generic.sa_family == AF_INET6) - return (socklen_t) sizeof (address.ipv6); - else - return (socklen_t) sizeof (address.ipv4); -} - -#if defined ZMQ_HAVE_WINDOWS -unsigned short zmq::tcp_address_t::family () const -#else -sa_family_t zmq::tcp_address_t::family () const -#endif -{ - return address.generic.sa_family; -} - -zmq::tcp_address_mask_t::tcp_address_mask_t () : - tcp_address_t () -{ - address_mask = -1; -} - -int zmq::tcp_address_mask_t::mask () const -{ - return address_mask; -} - -int zmq::tcp_address_mask_t::resolve (const char *name_, bool ipv6_) -{ - // Find '/' at the end that separates address from the cidr mask number. - // Allow empty mask clause and threat it like '/32' for ipv4 or '/128' for ipv6. - std::string addr_str, mask_str; - const char *delimiter = strrchr (name_, '/'); - if (delimiter != NULL) { - addr_str.assign (name_, delimiter - name_); - mask_str.assign (delimiter + 1); - if (mask_str.empty ()) { - errno = EINVAL; - return -1; - } - } - else - addr_str.assign (name_); - - // Parse address part using standard routines. - int rc = tcp_address_t::resolve_hostname (addr_str.c_str (), ipv6_); - if (rc != 0) - return rc; - - // Parse the cidr mask number. - if (mask_str.empty ()) { - if (address.generic.sa_family == AF_INET6) - address_mask = 128; - else - address_mask = 32; - } - else - if (mask_str == "0") { - address_mask = 0; - } - else { - int mask = atoi (mask_str.c_str ()); - if ( - (mask < 1) || - (address.generic.sa_family == AF_INET6 && mask > 128) || - (address.generic.sa_family != AF_INET6 && mask > 32) - ) { - errno = EINVAL; - return -1; - } - address_mask = mask; - } - - return 0; -} - -int zmq::tcp_address_mask_t::to_string (std::string &addr_) -{ - if (address.generic.sa_family != AF_INET && address.generic.sa_family != AF_INET6) { - addr_.clear (); - return -1; - } - if (address_mask == -1) { - addr_.clear (); - return -1; - } - - char hbuf[NI_MAXHOST]; - int rc = getnameinfo (addr (), addrlen (), hbuf, sizeof (hbuf), NULL, 0, NI_NUMERICHOST); - if (rc != 0) { - addr_.clear (); - return rc; - } - - if (address.generic.sa_family == AF_INET6) { - std::stringstream s; - s << "[" << hbuf << "]/" << address_mask; - addr_ = s.str (); - } - else { - std::stringstream s; - s << hbuf << "/" << address_mask; - addr_ = s.str (); - }; - return 0; -} - -bool zmq::tcp_address_mask_t::match_address (const struct sockaddr *ss, const socklen_t ss_len) const -{ - zmq_assert (address_mask != -1 && ss != NULL && ss_len >= (socklen_t) sizeof (struct sockaddr)); - - if (ss->sa_family != address.generic.sa_family) - return false; - - if (address_mask > 0) { - int mask; - const uint8_t *our_bytes, *their_bytes; - if (ss->sa_family == AF_INET6) { - zmq_assert (ss_len == sizeof (struct sockaddr_in6)); - their_bytes = (const uint8_t *) &(((const struct sockaddr_in6 *) ss)->sin6_addr); - our_bytes = (const uint8_t *) &address.ipv6.sin6_addr; - mask = sizeof (struct in6_addr) * 8; - } - else { - zmq_assert (ss_len == sizeof (struct sockaddr_in)); - their_bytes = (const uint8_t *) &(((const struct sockaddr_in *) ss)->sin_addr); - our_bytes = (const uint8_t *) &address.ipv4.sin_addr; - mask = sizeof (struct in_addr) * 8; - } - if (address_mask < mask) mask = address_mask; - - size_t full_bytes = mask / 8; - if (memcmp(our_bytes, their_bytes, full_bytes)) - return false; - - uint8_t last_byte_bits = (0xffU << (8 - (mask % 8))) & 0xffU; - if (last_byte_bits) { - if ((their_bytes[full_bytes] & last_byte_bits) != (our_bytes[full_bytes] & last_byte_bits)) - return false; - } - } - - return true; -} diff --git a/src/tcp_address.hpp b/src/tcp_address.hpp deleted file mode 100644 index 4aa95b2..0000000 --- a/src/tcp_address.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_TCP_ADDRESS_HPP_INCLUDED__ -#define __ZMQ_TCP_ADDRESS_HPP_INCLUDED__ - -#include "platform.hpp" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <sys/socket.h> -#include <netinet/in.h> -#endif - -namespace zmq -{ - - class tcp_address_t - { - public: - - tcp_address_t (); - tcp_address_t (const sockaddr *sa, socklen_t sa_len); - virtual ~tcp_address_t (); - - // This function translates textual TCP address into an address - // strcuture. If 'local' is true, names are resolved as local interface - // names. If it is false, names are resolved as remote hostnames. - // If 'ipv6' is true, the name may resolve to IPv6 address. - int resolve (const char *name_, bool local_, bool ipv6_); - - // The opposite to resolve() - virtual int to_string (std::string &addr_); - -#if defined ZMQ_HAVE_WINDOWS - unsigned short family () const; -#else - sa_family_t family () const; -#endif - const sockaddr *addr () const; - socklen_t addrlen () const; - - protected: - int resolve_nic_name (const char *nic_, bool ipv6_); - int resolve_interface (const char *interface_, bool ipv6_); - int resolve_hostname (const char *hostname_, bool ipv6_); - - union { - sockaddr generic; - sockaddr_in ipv4; - sockaddr_in6 ipv6; - } address; - }; - - class tcp_address_mask_t : public tcp_address_t - { - public: - tcp_address_mask_t (); - - // This function enhances tcp_address_t::resolve() with ability to parse - // additional cidr-like(/xx) mask value at the end of the name string. - // Works only with remote hostnames. - int resolve (const char *name_, bool ipv6_); - - // The opposite to resolve() - int to_string (std::string &addr_); - - int mask () const; - - bool match_address (const struct sockaddr *ss, const socklen_t ss_len) const; - - private: - int address_mask; - }; - -} - -#endif diff --git a/src/tcp_connecter.cpp b/src/tcp_connecter.cpp deleted file mode 100644 index 9e87a71..0000000 --- a/src/tcp_connecter.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <new> -#include <string> - -#include "tcp_connecter.hpp" -#include "stream_engine.hpp" -#include "io_thread.hpp" -#include "platform.hpp" -#include "random.hpp" -#include "err.hpp" -#include "ip.hpp" -#include "tcp.hpp" -#include "address.hpp" -#include "tcp_address.hpp" -#include "session_base.hpp" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netinet/in.h> -#include <netdb.h> -#include <fcntl.h> -#ifdef ZMQ_HAVE_OPENVMS -#include <ioctl.h> -#endif -#endif - -zmq::tcp_connecter_t::tcp_connecter_t (class io_thread_t *io_thread_, - class session_base_t *session_, const options_t &options_, - const address_t *addr_, bool delayed_start_) : - own_t (io_thread_, options_), - io_object_t (io_thread_), - addr (addr_), - s (retired_fd), - handle_valid (false), - delayed_start (delayed_start_), - timer_started (false), - session (session_), - current_reconnect_ivl(options.reconnect_ivl) -{ - zmq_assert (addr); - zmq_assert (addr->protocol == "tcp"); - addr->to_string (endpoint); - socket = session-> get_socket(); -} - -zmq::tcp_connecter_t::~tcp_connecter_t () -{ - zmq_assert (!timer_started); - zmq_assert (!handle_valid); - zmq_assert (s == retired_fd); -} - -void zmq::tcp_connecter_t::process_plug () -{ - if (delayed_start) - add_reconnect_timer (); - else - start_connecting (); -} - -void zmq::tcp_connecter_t::process_term (int linger_) -{ - if (timer_started) { - cancel_timer (reconnect_timer_id); - timer_started = false; - } - - if (handle_valid) { - rm_fd (handle); - handle_valid = false; - } - - if (s != retired_fd) - close (); - - own_t::process_term (linger_); -} - -void zmq::tcp_connecter_t::in_event () -{ - // We are not polling for incoming data, so we are actually called - // because of error here. However, we can get error on out event as well - // on some platforms, so we'll simply handle both events in the same way. - out_event (); -} - -void zmq::tcp_connecter_t::out_event () -{ - fd_t fd = connect (); - rm_fd (handle); - handle_valid = false; - - // Handle the error condition by attempt to reconnect. - if (fd == retired_fd) { - close (); - add_reconnect_timer(); - return; - } - - tune_tcp_socket (fd); - tune_tcp_keepalives (fd, options.tcp_keepalive, options.tcp_keepalive_cnt, options.tcp_keepalive_idle, options.tcp_keepalive_intvl); - - // Create the engine object for this connection. - stream_engine_t *engine = new (std::nothrow) - stream_engine_t (fd, options, endpoint); - alloc_assert (engine); - - // Attach the engine to the corresponding session object. - send_attach (session, engine); - - // Shut the connecter down. - terminate (); - - socket->event_connected (endpoint, fd); -} - -void zmq::tcp_connecter_t::timer_event (int id_) -{ - zmq_assert (id_ == reconnect_timer_id); - timer_started = false; - start_connecting (); -} - -void zmq::tcp_connecter_t::start_connecting () -{ - // Open the connecting socket. - int rc = open (); - - // Connect may succeed in synchronous manner. - if (rc == 0) { - handle = add_fd (s); - handle_valid = true; - out_event (); - } - - // Connection establishment may be delayed. Poll for its completion. - else - if (rc == -1 && errno == EINPROGRESS) { - handle = add_fd (s); - handle_valid = true; - set_pollout (handle); - socket->event_connect_delayed (endpoint, zmq_errno()); - } - - // Handle any other error condition by eventual reconnect. - else { - if (s != retired_fd) - close (); - add_reconnect_timer (); - } -} - -void zmq::tcp_connecter_t::add_reconnect_timer() -{ - int rc_ivl = get_new_reconnect_ivl(); - add_timer (rc_ivl, reconnect_timer_id); - socket->event_connect_retried (endpoint, rc_ivl); - timer_started = true; -} - -int zmq::tcp_connecter_t::get_new_reconnect_ivl () -{ - // The new interval is the current interval + random value. - int this_interval = current_reconnect_ivl + - (generate_random () % options.reconnect_ivl); - - // Only change the current reconnect interval if the maximum reconnect - // interval was set and if it's larger than the reconnect interval. - if (options.reconnect_ivl_max > 0 && - options.reconnect_ivl_max > options.reconnect_ivl) { - - // Calculate the next interval - current_reconnect_ivl = current_reconnect_ivl * 2; - if(current_reconnect_ivl >= options.reconnect_ivl_max) { - current_reconnect_ivl = options.reconnect_ivl_max; - } - } - return this_interval; -} - -int zmq::tcp_connecter_t::open () -{ - zmq_assert (s == retired_fd); - - // Create the socket. - s = open_socket (addr->resolved.tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP); -#ifdef ZMQ_HAVE_WINDOWS - if (s == INVALID_SOCKET) { - errno = wsa_error_to_errno (WSAGetLastError ()); - return -1; - } -#else - if (s == -1) - return -1; -#endif - - // On some systems, IPv4 mapping in IPv6 sockets is disabled by default. - // Switch it on in such cases. - if (addr->resolved.tcp_addr->family () == AF_INET6) - enable_ipv4_mapping (s); - - // Set the socket to non-blocking mode so that we get async connect(). - unblock_socket (s); - - // Set the socket buffer limits for the underlying socket. - if (options.sndbuf != 0) - set_tcp_send_buffer (s, options.sndbuf); - if (options.rcvbuf != 0) - set_tcp_receive_buffer (s, options.rcvbuf); - - // Connect to the remote peer. - int rc = ::connect ( - s, addr->resolved.tcp_addr->addr (), - addr->resolved.tcp_addr->addrlen ()); - - // Connect was successfull immediately. - if (rc == 0) - return 0; - - // Translate error codes indicating asynchronous connect has been - // launched to a uniform EINPROGRESS. -#ifdef ZMQ_HAVE_WINDOWS - const int error_code = WSAGetLastError (); - if (error_code == WSAEINPROGRESS || error_code == WSAEWOULDBLOCK) - errno = EINPROGRESS; - else - errno = wsa_error_to_errno (error_code); -#else - if (errno == EINTR) - errno = EINPROGRESS; -#endif - return -1; -} - -zmq::fd_t zmq::tcp_connecter_t::connect () -{ - // Async connect has finished. Check whether an error occurred - int err = 0; -#if defined ZMQ_HAVE_HPUX - int len = sizeof (err); -#else - socklen_t len = sizeof (err); -#endif - - int rc = getsockopt (s, SOL_SOCKET, SO_ERROR, (char*) &err, &len); - - // Assert if the error was caused by 0MQ bug. - // Networking problems are OK. No need to assert. -#ifdef ZMQ_HAVE_WINDOWS - zmq_assert (rc == 0); - if (err != 0) { - if (err == WSAECONNREFUSED || - err == WSAETIMEDOUT || - err == WSAECONNABORTED || - err == WSAEHOSTUNREACH || - err == WSAENETUNREACH || - err == WSAENETDOWN || - err == WSAEINVAL) - return retired_fd; - wsa_assert_no (err); - } -#else - - // Following code should handle both Berkeley-derived socket - // implementations and Solaris. - if (rc == -1) - err = errno; - if (err != 0) { - errno = err; - errno_assert ( - errno == ECONNREFUSED || - errno == ECONNRESET || - errno == ETIMEDOUT || - errno == EHOSTUNREACH || - errno == ENETUNREACH || - errno == ENETDOWN || - errno == EINVAL); - return retired_fd; - } -#endif - - // Return the newly connected socket. - fd_t result = s; - s = retired_fd; - return result; -} - -void zmq::tcp_connecter_t::close () -{ - zmq_assert (s != retired_fd); -#ifdef ZMQ_HAVE_WINDOWS - int rc = closesocket (s); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = ::close (s); - errno_assert (rc == 0); -#endif - socket->event_closed (endpoint, s); - s = retired_fd; -} diff --git a/src/tcp_connecter.hpp b/src/tcp_connecter.hpp deleted file mode 100644 index 5de3a48..0000000 --- a/src/tcp_connecter.hpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __TCP_CONNECTER_HPP_INCLUDED__ -#define __TCP_CONNECTER_HPP_INCLUDED__ - -#include "fd.hpp" -#include "own.hpp" -#include "stdint.hpp" -#include "io_object.hpp" -#include "../include/zmq.h" - -namespace zmq -{ - - class io_thread_t; - class session_base_t; - struct address_t; - - class tcp_connecter_t : public own_t, public io_object_t - { - public: - - // If 'delayed_start' is true connecter first waits for a while, - // then starts connection process. - tcp_connecter_t (zmq::io_thread_t *io_thread_, - zmq::session_base_t *session_, const options_t &options_, - const address_t *addr_, bool delayed_start_); - ~tcp_connecter_t (); - - private: - - // ID of the timer used to delay the reconnection. - enum {reconnect_timer_id = 1}; - - // Handlers for incoming commands. - void process_plug (); - void process_term (int linger_); - - // Handlers for I/O events. - void in_event (); - void out_event (); - void timer_event (int id_); - - // Internal function to start the actual connection establishment. - void start_connecting (); - - // Internal function to add a reconnect timer - void add_reconnect_timer(); - - // Internal function to return a reconnect backoff delay. - // Will modify the current_reconnect_ivl used for next call - // Returns the currently used interval - int get_new_reconnect_ivl (); - - // Open TCP connecting socket. Returns -1 in case of error, - // 0 if connect was successfull immediately. Returns -1 with - // EAGAIN errno if async connect was launched. - int open (); - - // Close the connecting socket. - void close (); - - // Get the file descriptor of newly created connection. Returns - // retired_fd if the connection was unsuccessfull. - fd_t connect (); - - // Address to connect to. Owned by session_base_t. - const address_t *addr; - - // Underlying socket. - fd_t s; - - // Handle corresponding to the listening socket. - handle_t handle; - - // If true file descriptor is registered with the poller and 'handle' - // contains valid value. - bool handle_valid; - - // If true, connecter is waiting a while before trying to connect. - const bool delayed_start; - - // True iff a timer has been started. - bool timer_started; - - // Reference to the session we belong to. - zmq::session_base_t *session; - - // Current reconnect ivl, updated for backoff strategy - int current_reconnect_ivl; - - // String representation of endpoint to connect to - std::string endpoint; - - // Socket - zmq::socket_base_t *socket; - - tcp_connecter_t (const tcp_connecter_t&); - const tcp_connecter_t &operator = (const tcp_connecter_t&); - }; - -} - -#endif diff --git a/src/tcp_listener.cpp b/src/tcp_listener.cpp deleted file mode 100644 index 89e146b..0000000 --- a/src/tcp_listener.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <new> - -#include <string> - -#include "platform.hpp" -#include "tcp_listener.hpp" -#include "stream_engine.hpp" -#include "io_thread.hpp" -#include "session_base.hpp" -#include "config.hpp" -#include "err.hpp" -#include "ip.hpp" -#include "tcp.hpp" -#include "socket_base.hpp" - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netinet/in.h> -#include <netdb.h> -#include <fcntl.h> -#endif - -#ifdef ZMQ_HAVE_OPENVMS -#include <ioctl.h> -#endif - -zmq::tcp_listener_t::tcp_listener_t (io_thread_t *io_thread_, - socket_base_t *socket_, const options_t &options_) : - own_t (io_thread_, options_), - io_object_t (io_thread_), - s (retired_fd), - socket (socket_) -{ -} - -zmq::tcp_listener_t::~tcp_listener_t () -{ - zmq_assert (s == retired_fd); -} - -void zmq::tcp_listener_t::process_plug () -{ - // Start polling for incoming connections. - handle = add_fd (s); - set_pollin (handle); -} - -void zmq::tcp_listener_t::process_term (int linger_) -{ - rm_fd (handle); - close (); - own_t::process_term (linger_); -} - -void zmq::tcp_listener_t::in_event () -{ - fd_t fd = accept (); - - // If connection was reset by the peer in the meantime, just ignore it. - // TODO: Handle specific errors like ENFILE/EMFILE etc. - if (fd == retired_fd) { - socket->event_accept_failed (endpoint, zmq_errno()); - return; - } - - tune_tcp_socket (fd); - tune_tcp_keepalives (fd, options.tcp_keepalive, options.tcp_keepalive_cnt, options.tcp_keepalive_idle, options.tcp_keepalive_intvl); - - // Create the engine object for this connection. - stream_engine_t *engine = new (std::nothrow) - stream_engine_t (fd, options, endpoint); - alloc_assert (engine); - - // Choose I/O thread to run connecter in. Given that we are already - // running in an I/O thread, there must be at least one available. - io_thread_t *io_thread = choose_io_thread (options.affinity); - zmq_assert (io_thread); - - // Create and launch a session object. - session_base_t *session = session_base_t::create (io_thread, false, socket, - options, NULL); - errno_assert (session); - session->inc_seqnum (); - launch_child (session); - send_attach (session, engine, false); - socket->event_accepted (endpoint, fd); -} - -void zmq::tcp_listener_t::close () -{ - zmq_assert (s != retired_fd); -#ifdef ZMQ_HAVE_WINDOWS - int rc = closesocket (s); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = ::close (s); - errno_assert (rc == 0); -#endif - socket->event_closed (endpoint, s); - s = retired_fd; -} - -int zmq::tcp_listener_t::get_address (std::string &addr_) -{ - // Get the details of the TCP socket - struct sockaddr_storage ss; -#ifdef ZMQ_HAVE_HPUX - int sl = sizeof (ss); -#else - socklen_t sl = sizeof (ss); -#endif - int rc = getsockname (s, (struct sockaddr *) &ss, &sl); - - if (rc != 0) { - addr_.clear (); - return rc; - } - - tcp_address_t addr ((struct sockaddr *) &ss, sl); - return addr.to_string (addr_); -} - -int zmq::tcp_listener_t::set_address (const char *addr_) -{ - // Convert the textual address into address structure. - int rc = address.resolve (addr_, true, options.ipv6); - if (rc != 0) - return -1; - - // Create a listening socket. - s = open_socket (address.family (), SOCK_STREAM, IPPROTO_TCP); -#ifdef ZMQ_HAVE_WINDOWS - if (s == INVALID_SOCKET) - errno = wsa_error_to_errno (WSAGetLastError ()); -#endif - - // IPv6 address family not supported, try automatic downgrade to IPv4. - if (address.family () == AF_INET6 - && errno == EAFNOSUPPORT - && options.ipv6) { - rc = address.resolve (addr_, true, true); - if (rc != 0) - return rc; - s = ::socket (address.family (), SOCK_STREAM, IPPROTO_TCP); - } - -#ifdef ZMQ_HAVE_WINDOWS - if (s == INVALID_SOCKET) { - errno = wsa_error_to_errno (WSAGetLastError ()); - return -1; - } -#if !defined _WIN32_WCE - // On Windows, preventing sockets to be inherited by child processes. - BOOL brc = SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); - win_assert (brc); -#endif -#else - if (s == -1) - return -1; -#endif - - // On some systems, IPv4 mapping in IPv6 sockets is disabled by default. - // Switch it on in such cases. - if (address.family () == AF_INET6) - enable_ipv4_mapping (s); - - // Set the socket buffer limits for the underlying socket. - if (options.sndbuf != 0) - set_tcp_send_buffer (s, options.sndbuf); - if (options.rcvbuf != 0) - set_tcp_receive_buffer (s, options.rcvbuf); - - // Allow reusing of the address. - int flag = 1; -#ifdef ZMQ_HAVE_WINDOWS - rc = setsockopt (s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, - (const char*) &flag, sizeof (int)); - wsa_assert (rc != SOCKET_ERROR); -#else - rc = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)); - errno_assert (rc == 0); -#endif - - address.to_string (endpoint); - - // Bind the socket to the network interface and port. - rc = bind (s, address.addr (), address.addrlen ()); -#ifdef ZMQ_HAVE_WINDOWS - if (rc == SOCKET_ERROR) { - errno = wsa_error_to_errno (WSAGetLastError ()); - goto error; - } -#else - if (rc != 0) - goto error; -#endif - - // Listen for incomming connections. - rc = listen (s, options.backlog); -#ifdef ZMQ_HAVE_WINDOWS - if (rc == SOCKET_ERROR) { - errno = wsa_error_to_errno (WSAGetLastError ()); - goto error; - } -#else - if (rc != 0) - goto error; -#endif - - socket->event_listening (endpoint, s); - return 0; - -error: - int err = errno; - close (); - errno = err; - return -1; -} - -zmq::fd_t zmq::tcp_listener_t::accept () -{ - // The situation where connection cannot be accepted due to insufficient - // resources is considered valid and treated by ignoring the connection. - // Accept one connection and deal with different failure modes. - zmq_assert (s != retired_fd); - - struct sockaddr_storage ss; - memset (&ss, 0, sizeof (ss)); -#ifdef ZMQ_HAVE_HPUX - int ss_len = sizeof (ss); -#else - socklen_t ss_len = sizeof (ss); -#endif - fd_t sock = ::accept (s, (struct sockaddr *) &ss, &ss_len); - -#ifdef ZMQ_HAVE_WINDOWS - if (sock == INVALID_SOCKET) { - wsa_assert (WSAGetLastError () == WSAEWOULDBLOCK || - WSAGetLastError () == WSAECONNRESET || - WSAGetLastError () == WSAEMFILE || - WSAGetLastError () == WSAENOBUFS); - return retired_fd; - } -#if !defined _WIN32_WCE - // On Windows, preventing sockets to be inherited by child processes. - BOOL brc = SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0); - win_assert (brc); -#endif -#else - if (sock == -1) { - errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINTR || errno == ECONNABORTED || errno == EPROTO || - errno == ENOBUFS || errno == ENOMEM || errno == EMFILE || - errno == ENFILE); - return retired_fd; - } -#endif - - if (!options.tcp_accept_filters.empty ()) { - bool matched = false; - for (options_t::tcp_accept_filters_t::size_type i = 0; i != options.tcp_accept_filters.size (); ++i) { - if (options.tcp_accept_filters[i].match_address ((struct sockaddr *) &ss, ss_len)) { - matched = true; - break; - } - } - if (!matched) { -#ifdef ZMQ_HAVE_WINDOWS - int rc = closesocket (sock); - wsa_assert (rc != SOCKET_ERROR); -#else - int rc = ::close (sock); - errno_assert (rc == 0); -#endif - return retired_fd; - } - } - - return sock; -} diff --git a/src/tcp_listener.hpp b/src/tcp_listener.hpp deleted file mode 100644 index 8063305..0000000 --- a/src/tcp_listener.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_TCP_LISTENER_HPP_INCLUDED__ -#define __ZMQ_TCP_LISTENER_HPP_INCLUDED__ - -#include "fd.hpp" -#include "own.hpp" -#include "stdint.hpp" -#include "io_object.hpp" -#include "tcp_address.hpp" -#include "../include/zmq.h" - -namespace zmq -{ - - class io_thread_t; - class socket_base_t; - - class tcp_listener_t : public own_t, public io_object_t - { - public: - - tcp_listener_t (zmq::io_thread_t *io_thread_, - zmq::socket_base_t *socket_, const options_t &options_); - ~tcp_listener_t (); - - // Set address to listen on. - int set_address (const char *addr_); - - // Get the bound address for use with wildcard - int get_address (std::string &addr_); - - private: - - // Handlers for incoming commands. - void process_plug (); - void process_term (int linger_); - - // Handlers for I/O events. - void in_event (); - - // Close the listening socket. - void close (); - - // Accept the new connection. Returns the file descriptor of the - // newly created connection. The function may return retired_fd - // if the connection was dropped while waiting in the listen backlog - // or was denied because of accept filters. - fd_t accept (); - - // Address to listen on. - tcp_address_t address; - - // Underlying socket. - fd_t s; - - // Handle corresponding to the listening socket. - handle_t handle; - - // Socket the listerner belongs to. - zmq::socket_base_t *socket; - - // String representation of endpoint to bind to - std::string endpoint; - - tcp_listener_t (const tcp_listener_t&); - const tcp_listener_t &operator = (const tcp_listener_t&); - }; - -} - -#endif diff --git a/src/thread.cpp b/src/thread.cpp deleted file mode 100644 index e9eeceb..0000000 --- a/src/thread.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "thread.hpp" -#include "err.hpp" -#include "platform.hpp" - -#ifdef ZMQ_HAVE_WINDOWS - -extern "C" -{ -#if defined _WIN32_WCE - static DWORD thread_routine (LPVOID arg_) -#else - static unsigned int __stdcall thread_routine (void *arg_) -#endif - { - zmq::thread_t *self = (zmq::thread_t*) arg_; - self->tfn (self->arg); - return 0; - } -} - -void zmq::thread_t::start (thread_fn *tfn_, void *arg_) -{ - tfn = tfn_; - arg =arg_; -#if defined _WIN32_WCE - descriptor = (HANDLE) CreateThread (NULL, 0, - &::thread_routine, this, 0 , NULL); -#else - descriptor = (HANDLE) _beginthreadex (NULL, 0, - &::thread_routine, this, 0 , NULL); -#endif - win_assert (descriptor != NULL); -} - -void zmq::thread_t::stop () -{ - DWORD rc = WaitForSingleObject (descriptor, INFINITE); - win_assert (rc != WAIT_FAILED); - BOOL rc2 = CloseHandle (descriptor); - win_assert (rc2 != 0); -} - -#else - -#include <signal.h> - -extern "C" -{ - static void *thread_routine (void *arg_) - { -#if !defined ZMQ_HAVE_OPENVMS && !defined ZMQ_HAVE_ANDROID - // Following code will guarantee more predictable latencies as it'll - // disallow any signal handling in the I/O thread. - sigset_t signal_set; - int rc = sigfillset (&signal_set); - errno_assert (rc == 0); - rc = pthread_sigmask (SIG_BLOCK, &signal_set, NULL); - posix_assert (rc); -#endif - - zmq::thread_t *self = (zmq::thread_t*) arg_; - self->tfn (self->arg); - return NULL; - } -} - -void zmq::thread_t::start (thread_fn *tfn_, void *arg_) -{ - tfn = tfn_; - arg =arg_; - int rc = pthread_create (&descriptor, NULL, thread_routine, this); - posix_assert (rc); -} - -void zmq::thread_t::stop () -{ - int rc = pthread_join (descriptor, NULL); - posix_assert (rc); -} - -#endif - - - - - diff --git a/src/thread.hpp b/src/thread.hpp deleted file mode 100644 index 0acb7d9..0000000 --- a/src/thread.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_THREAD_HPP_INCLUDED__ -#define __ZMQ_THREAD_HPP_INCLUDED__ - -#include "platform.hpp" - -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <pthread.h> -#endif - -namespace zmq -{ - - typedef void (thread_fn) (void*); - - // Class encapsulating OS thread. Thread initiation/termination is done - // using special functions rather than in constructor/destructor so that - // thread isn't created during object construction by accident, causing - // newly created thread to access half-initialised object. Same applies - // to the destruction process: Thread should be terminated before object - // destruction begins, otherwise it can access half-destructed object. - - class thread_t - { - public: - - inline thread_t () - { - } - - // Creates OS thread. 'tfn' is main thread function. It'll be passed - // 'arg' as an argument. - void start (thread_fn *tfn_, void *arg_); - - // Waits for thread termination. - void stop (); - - // These are internal members. They should be private, however then - // they would not be accessible from the main C routine of the thread. - thread_fn *tfn; - void *arg; - - private: - -#ifdef ZMQ_HAVE_WINDOWS - HANDLE descriptor; -#else - pthread_t descriptor; -#endif - - thread_t (const thread_t&); - const thread_t &operator = (const thread_t&); - }; - -} - -#endif diff --git a/src/trie.cpp b/src/trie.cpp deleted file mode 100644 index e495499..0000000 --- a/src/trie.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> - -#include <new> -#include <algorithm> - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "err.hpp" -#include "trie.hpp" - -zmq::trie_t::trie_t () : - refcnt (0), - min (0), - count (0), - live_nodes (0) -{ -} - -zmq::trie_t::~trie_t () -{ - if (count == 1) { - zmq_assert (next.node); - delete next.node; - next.node = 0; - } - else - if (count > 1) { - for (unsigned short i = 0; i != count; ++i) - delete next.table [i]; - free (next.table); - } -} - -bool zmq::trie_t::add (unsigned char *prefix_, size_t size_) -{ - // We are at the node corresponding to the prefix. We are done. - if (!size_) { - ++refcnt; - return refcnt == 1; - } - - unsigned char c = *prefix_; - if (c < min || c >= min + count) { - - // The character is out of range of currently handled - // charcters. We have to extend the table. - if (!count) { - min = c; - count = 1; - next.node = NULL; - } - else - if (count == 1) { - unsigned char oldc = min; - trie_t *oldp = next.node; - count = (min < c ? c - min : min - c) + 1; - next.table = (trie_t**) - malloc (sizeof (trie_t*) * count); - alloc_assert (next.table); - for (unsigned short i = 0; i != count; ++i) - next.table [i] = 0; - min = std::min (min, c); - next.table [oldc - min] = oldp; - } - else - if (min < c) { - // The new character is above the current character range. - unsigned short old_count = count; - count = c - min + 1; - next.table = (trie_t**) realloc ((void*) next.table, - sizeof (trie_t*) * count); - zmq_assert (next.table); - for (unsigned short i = old_count; i != count; i++) - next.table [i] = NULL; - } - else { - - // The new character is below the current character range. - unsigned short old_count = count; - count = (min + old_count) - c; - next.table = (trie_t**) realloc ((void*) next.table, - sizeof (trie_t*) * count); - zmq_assert (next.table); - memmove (next.table + min - c, next.table, - old_count * sizeof (trie_t*)); - for (unsigned short i = 0; i != min - c; i++) - next.table [i] = NULL; - min = c; - } - } - - // If next node does not exist, create one. - if (count == 1) { - if (!next.node) { - next.node = new (std::nothrow) trie_t; - alloc_assert (next.node); - ++live_nodes; - zmq_assert (live_nodes == 1); - } - return next.node->add (prefix_ + 1, size_ - 1); - } - else { - if (!next.table [c - min]) { - next.table [c - min] = new (std::nothrow) trie_t; - alloc_assert (next.table [c - min]); - ++live_nodes; - zmq_assert (live_nodes > 1); - } - return next.table [c - min]->add (prefix_ + 1, size_ - 1); - } -} - -bool zmq::trie_t::rm (unsigned char *prefix_, size_t size_) -{ - // TODO: Shouldn't an error be reported if the key does not exist? - if (!size_) { - if (!refcnt) - return false; - refcnt--; - return refcnt == 0; - } - unsigned char c = *prefix_; - if (!count || c < min || c >= min + count) - return false; - - trie_t *next_node = - count == 1 ? next.node : next.table [c - min]; - - if (!next_node) - return false; - - bool ret = next_node->rm (prefix_ + 1, size_ - 1); - - // Prune redundant nodes - if (next_node->is_redundant ()) { - delete next_node; - zmq_assert (count > 0); - - if (count == 1) { - // The just pruned node is was the only live node - next.node = 0; - count = 0; - --live_nodes; - zmq_assert (live_nodes == 0); - } - else { - next.table [c - min] = 0; - zmq_assert (live_nodes > 1); - --live_nodes; - - // Compact the table if possible - if (live_nodes == 1) { - // We can switch to using the more compact single-node - // representation since the table only contains one live node - trie_t *node = 0; - // Since we always compact the table the pruned node must - // either be the left-most or right-most ptr in the node - // table - if (c == min) { - // The pruned node is the left-most node ptr in the - // node table => keep the right-most node - node = next.table [count - 1]; - min += count - 1; - } - else - if (c == min + count - 1) { - // The pruned node is the right-most node ptr in the - // node table => keep the left-most node - node = next.table [0]; - } - zmq_assert (node); - free (next.table); - next.node = node; - count = 1; - } - else - if (c == min) { - // We can compact the table "from the left". - // Find the left-most non-null node ptr, which we'll use as - // our new min - unsigned char new_min = min; - for (unsigned short i = 1; i < count; ++i) { - if (next.table [i]) { - new_min = i + min; - break; - } - } - zmq_assert (new_min != min); - - trie_t **old_table = next.table; - zmq_assert (new_min > min); - zmq_assert (count > new_min - min); - - count = count - (new_min - min); - next.table = (trie_t**) malloc (sizeof (trie_t*) * count); - alloc_assert (next.table); - - memmove (next.table, old_table + (new_min - min), - sizeof (trie_t*) * count); - free (old_table); - - min = new_min; - } - else - if (c == min + count - 1) { - // We can compact the table "from the right". - // Find the right-most non-null node ptr, which we'll use to - // determine the new table size - unsigned short new_count = count; - for (unsigned short i = 1; i < count; ++i) { - if (next.table [count - 1 - i]) { - new_count = count - i; - break; - } - } - zmq_assert (new_count != count); - count = new_count; - - trie_t **old_table = next.table; - next.table = (trie_t**) malloc (sizeof (trie_t*) * count); - alloc_assert (next.table); - - memmove (next.table, old_table, sizeof (trie_t*) * count); - free (old_table); - } - } - } - return ret; -} - -bool zmq::trie_t::check (unsigned char *data_, size_t size_) -{ - // This function is on critical path. It deliberately doesn't use - // recursion to get a bit better performance. - trie_t *current = this; - while (true) { - - // We've found a corresponding subscription! - if (current->refcnt) - return true; - - // We've checked all the data and haven't found matching subscription. - if (!size_) - return false; - - // If there's no corresponding slot for the first character - // of the prefix, the message does not match. - unsigned char c = *data_; - if (c < current->min || c >= current->min + current->count) - return false; - - // Move to the next character. - if (current->count == 1) - current = current->next.node; - else { - current = current->next.table [c - current->min]; - if (!current) - return false; - } - data_++; - size_--; - } -} - -void zmq::trie_t::apply (void (*func_) (unsigned char *data_, size_t size_, - void *arg_), void *arg_) -{ - unsigned char *buff = NULL; - apply_helper (&buff, 0, 0, func_, arg_); - free (buff); -} - -void zmq::trie_t::apply_helper ( - unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), void *arg_) -{ - // If this node is a subscription, apply the function. - if (refcnt) - func_ (*buff_, buffsize_, arg_); - - // Adjust the buffer. - if (buffsize_ >= maxbuffsize_) { - maxbuffsize_ = buffsize_ + 256; - *buff_ = (unsigned char*) realloc (*buff_, maxbuffsize_); - zmq_assert (*buff_); - } - - // If there are no subnodes in the trie, return. - if (count == 0) - return; - - // If there's one subnode (optimisation). - if (count == 1) { - (*buff_) [buffsize_] = min; - buffsize_++; - next.node->apply_helper (buff_, buffsize_, maxbuffsize_, func_, arg_); - return; - } - - // If there are multiple subnodes. - for (unsigned short c = 0; c != count; c++) { - (*buff_) [buffsize_] = min + c; - if (next.table [c]) - next.table [c]->apply_helper (buff_, buffsize_ + 1, maxbuffsize_, - func_, arg_); - } -} - -bool zmq::trie_t::is_redundant () const -{ - return refcnt == 0 && live_nodes == 0; -} diff --git a/src/trie.hpp b/src/trie.hpp deleted file mode 100644 index 43ae1de..0000000 --- a/src/trie.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_TRIE_HPP_INCLUDED__ -#define __ZMQ_TRIE_HPP_INCLUDED__ - -#include <stddef.h> - -#include "stdint.hpp" - -namespace zmq -{ - - class trie_t - { - public: - - trie_t (); - ~trie_t (); - - // Add key to the trie. Returns true if this is a new item in the trie - // rather than a duplicate. - bool add (unsigned char *prefix_, size_t size_); - - // Remove key from the trie. Returns true if the item is actually - // removed from the trie. - bool rm (unsigned char *prefix_, size_t size_); - - // Check whether particular key is in the trie. - bool check (unsigned char *data_, size_t size_); - - // Apply the function supplied to each subscription in the trie. - void apply (void (*func_) (unsigned char *data_, size_t size_, - void *arg_), void *arg_); - - private: - - void apply_helper ( - unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_, - void (*func_) (unsigned char *data_, size_t size_, void *arg_), - void *arg_); - bool is_redundant () const; - - uint32_t refcnt; - unsigned char min; - unsigned short count; - unsigned short live_nodes; - union { - class trie_t *node; - class trie_t **table; - } next; - - trie_t (const trie_t&); - const trie_t &operator = (const trie_t&); - }; - -} - -#endif - diff --git a/src/v1_decoder.cpp b/src/v1_decoder.cpp deleted file mode 100644 index b50f67f..0000000 --- a/src/v1_decoder.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> -#include <string.h> -#include <limits> - -#include "platform.hpp" -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "decoder.hpp" -#include "v1_decoder.hpp" -#include "likely.hpp" -#include "wire.hpp" -#include "err.hpp" - -zmq::v1_decoder_t::v1_decoder_t (size_t bufsize_, int64_t maxmsgsize_) : - decoder_base_t <v1_decoder_t> (bufsize_), - maxmsgsize (maxmsgsize_) -{ - int rc = in_progress.init (); - errno_assert (rc == 0); - - // At the beginning, read one byte and go to one_byte_size_ready state. - next_step (tmpbuf, 1, &v1_decoder_t::one_byte_size_ready); -} - -zmq::v1_decoder_t::~v1_decoder_t () -{ - int rc = in_progress.close (); - errno_assert (rc == 0); -} - -int zmq::v1_decoder_t::one_byte_size_ready () -{ - // First byte of size is read. If it is 0xff read 8-byte size. - // Otherwise allocate the buffer for message data and read the - // message data into it. - if (*tmpbuf == 0xff) - next_step (tmpbuf, 8, &v1_decoder_t::eight_byte_size_ready); - else { - - // There has to be at least one byte (the flags) in the message). - if (!*tmpbuf) { - errno = EPROTO; - return -1; - } - - if (maxmsgsize >= 0 && (int64_t) (*tmpbuf - 1) > maxmsgsize) { - errno = EMSGSIZE; - return -1; - } - - // in_progress is initialised at this point so in theory we should - // close it before calling zmq_msg_init_size, however, it's a 0-byte - // message and thus we can treat it as uninitialised... - int rc = in_progress.init_size (*tmpbuf - 1); - if (rc != 0) { - errno_assert (errno == ENOMEM); - rc = in_progress.init (); - errno_assert (rc == 0); - errno = ENOMEM; - return -1; - } - - next_step (tmpbuf, 1, &v1_decoder_t::flags_ready); - } - return 0; -} - -int zmq::v1_decoder_t::eight_byte_size_ready () -{ - // 8-byte payload length is read. Allocate the buffer - // for message body and read the message data into it. - const uint64_t payload_length = get_uint64 (tmpbuf); - - // There has to be at least one byte (the flags) in the message). - if (payload_length == 0) { - errno = EPROTO; - return -1; - } - - // Message size must not exceed the maximum allowed size. - if (maxmsgsize >= 0 && payload_length - 1 > (uint64_t) maxmsgsize) { - errno = EMSGSIZE; - return -1; - } - - // Message size must fit within range of size_t data type. - if (payload_length - 1 > std::numeric_limits <size_t>::max ()) { - errno = EMSGSIZE; - return -1; - } - - const size_t msg_size = static_cast <size_t> (payload_length - 1); - - // in_progress is initialised at this point so in theory we should - // close it before calling init_size, however, it's a 0-byte - // message and thus we can treat it as uninitialised... - int rc = in_progress.init_size (msg_size); - if (rc != 0) { - errno_assert (errno == ENOMEM); - rc = in_progress.init (); - errno_assert (rc == 0); - errno = ENOMEM; - return -1; - } - - next_step (tmpbuf, 1, &v1_decoder_t::flags_ready); - return 0; -} - -int zmq::v1_decoder_t::flags_ready () -{ - // Store the flags from the wire into the message structure. - in_progress.set_flags (tmpbuf [0] & msg_t::more); - - next_step (in_progress.data (), in_progress.size (), - &v1_decoder_t::message_ready); - - return 0; -} - -int zmq::v1_decoder_t::message_ready () -{ - // Message is completely read. Push it further and start reading - // new message. (in_progress is a 0-byte message after this point.) - next_step (tmpbuf, 1, &v1_decoder_t::one_byte_size_ready); - return 1; -} diff --git a/src/v1_decoder.hpp b/src/v1_decoder.hpp deleted file mode 100644 index 1708118..0000000 --- a/src/v1_decoder.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_V1_DECODER_HPP_INCLUDED__ -#define __ZMQ_V1_DECODER_HPP_INCLUDED__ - -#include "decoder.hpp" - -namespace zmq -{ - // Decoder for ZMTP/1.0 protocol. Converts data batches into messages. - - class v1_decoder_t : public decoder_base_t <v1_decoder_t> - { - public: - - v1_decoder_t (size_t bufsize_, int64_t maxmsgsize_); - ~v1_decoder_t (); - - virtual msg_t *msg () { return &in_progress; } - - private: - - int one_byte_size_ready (); - int eight_byte_size_ready (); - int flags_ready (); - int message_ready (); - - unsigned char tmpbuf [8]; - msg_t in_progress; - - int64_t maxmsgsize; - - v1_decoder_t (const v1_decoder_t&); - void operator = (const v1_decoder_t&); - }; - -} - -#endif - diff --git a/src/v1_encoder.cpp b/src/v1_encoder.cpp deleted file mode 100644 index e2b6fd0..0000000 --- a/src/v1_encoder.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "encoder.hpp" -#include "v1_encoder.hpp" -#include "likely.hpp" -#include "wire.hpp" - -zmq::v1_encoder_t::v1_encoder_t (size_t bufsize_) : - encoder_base_t <v1_encoder_t> (bufsize_) -{ - // Write 0 bytes to the batch and go to message_ready state. - next_step (NULL, 0, &v1_encoder_t::message_ready, true); -} - -zmq::v1_encoder_t::~v1_encoder_t () -{ -} - -void zmq::v1_encoder_t::size_ready () -{ - // Write message body into the buffer. - next_step (in_progress->data (), in_progress->size (), - &v1_encoder_t::message_ready, true); -} - -void zmq::v1_encoder_t::message_ready () -{ - // Get the message size. - size_t size = in_progress->size (); - - // Account for the 'flags' byte. - size++; - - // For messages less than 255 bytes long, write one byte of message size. - // For longer messages write 0xff escape character followed by 8-byte - // message size. In both cases 'flags' field follows. - if (size < 255) { - tmpbuf [0] = (unsigned char) size; - tmpbuf [1] = (in_progress->flags () & msg_t::more); - next_step (tmpbuf, 2, &v1_encoder_t::size_ready, false); - } - else { - tmpbuf [0] = 0xff; - put_uint64 (tmpbuf + 1, size); - tmpbuf [9] = (in_progress->flags () & msg_t::more); - next_step (tmpbuf, 10, &v1_encoder_t::size_ready, false); - } -} diff --git a/src/v1_encoder.hpp b/src/v1_encoder.hpp deleted file mode 100644 index 7d5ab7d..0000000 --- a/src/v1_encoder.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_V1_ENCODER_HPP_INCLUDED__ -#define __ZMQ_V1_ENCODER_HPP_INCLUDED__ - -#include "encoder.hpp" - -namespace zmq -{ - // Encoder for ZMTP/1.0 protocol. Converts messages into data batches. - - class v1_encoder_t : public encoder_base_t <v1_encoder_t> - { - public: - - v1_encoder_t (size_t bufsize_); - ~v1_encoder_t (); - - private: - - void size_ready (); - void message_ready (); - - unsigned char tmpbuf [10]; - - v1_encoder_t (const v1_encoder_t&); - const v1_encoder_t &operator = (const v1_encoder_t&); - }; -} - -#endif - diff --git a/src/v2_decoder.cpp b/src/v2_decoder.cpp deleted file mode 100644 index a4f36e9..0000000 --- a/src/v2_decoder.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> -#include <string.h> - -#include "platform.hpp" -#ifdef ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#endif - -#include "v2_protocol.hpp" -#include "v2_decoder.hpp" -#include "likely.hpp" -#include "wire.hpp" -#include "err.hpp" - -zmq::v2_decoder_t::v2_decoder_t (size_t bufsize_, int64_t maxmsgsize_) : - decoder_base_t <v2_decoder_t> (bufsize_), - msg_flags (0), - maxmsgsize (maxmsgsize_) -{ - int rc = in_progress.init (); - errno_assert (rc == 0); - - // At the beginning, read one byte and go to flags_ready state. - next_step (tmpbuf, 1, &v2_decoder_t::flags_ready); -} - -zmq::v2_decoder_t::~v2_decoder_t () -{ - int rc = in_progress.close (); - errno_assert (rc == 0); -} - -int zmq::v2_decoder_t::flags_ready () -{ - msg_flags = 0; - if (tmpbuf [0] & v2_protocol_t::more_flag) - msg_flags |= msg_t::more; - if (tmpbuf [0] & v2_protocol_t::command_flag) - msg_flags |= msg_t::command; - - // The payload length is either one or eight bytes, - // depending on whether the 'large' bit is set. - if (tmpbuf [0] & v2_protocol_t::large_flag) - next_step (tmpbuf, 8, &v2_decoder_t::eight_byte_size_ready); - else - next_step (tmpbuf, 1, &v2_decoder_t::one_byte_size_ready); - - return 0; -} - -int zmq::v2_decoder_t::one_byte_size_ready () -{ - // Message size must not exceed the maximum allowed size. - if (maxmsgsize >= 0) - if (unlikely (tmpbuf [0] > static_cast <uint64_t> (maxmsgsize))) { - errno = EMSGSIZE; - return -1; - } - - // in_progress is initialised at this point so in theory we should - // close it before calling zmq_msg_init_size, however, it's a 0-byte - // message and thus we can treat it as uninitialised... - int rc = in_progress.init_size (tmpbuf [0]); - if (unlikely (rc)) { - errno_assert (errno == ENOMEM); - rc = in_progress.init (); - errno_assert (rc == 0); - errno = ENOMEM; - return -1; - } - - in_progress.set_flags (msg_flags); - next_step (in_progress.data (), in_progress.size (), - &v2_decoder_t::message_ready); - - return 0; -} - -int zmq::v2_decoder_t::eight_byte_size_ready () -{ - // The payload size is encoded as 64-bit unsigned integer. - // The most significant byte comes first. - const uint64_t msg_size = get_uint64 (tmpbuf); - - // Message size must not exceed the maximum allowed size. - if (maxmsgsize >= 0) - if (unlikely (msg_size > static_cast <uint64_t> (maxmsgsize))) { - errno = EMSGSIZE; - return -1; - } - - // Message size must fit into size_t data type. - if (unlikely (msg_size != static_cast <size_t> (msg_size))) { - errno = EMSGSIZE; - return -1; - } - - // in_progress is initialised at this point so in theory we should - // close it before calling init_size, however, it's a 0-byte - // message and thus we can treat it as uninitialised. - int rc = in_progress.init_size (static_cast <size_t> (msg_size)); - if (unlikely (rc)) { - errno_assert (errno == ENOMEM); - rc = in_progress.init (); - errno_assert (rc == 0); - errno = ENOMEM; - return -1; - } - - in_progress.set_flags (msg_flags); - next_step (in_progress.data (), in_progress.size (), - &v2_decoder_t::message_ready); - - return 0; -} - -int zmq::v2_decoder_t::message_ready () -{ - // Message is completely read. Signal this to the caller - // and prepare to decode next message. - next_step (tmpbuf, 1, &v2_decoder_t::flags_ready); - return 1; -} diff --git a/src/v2_decoder.hpp b/src/v2_decoder.hpp deleted file mode 100644 index a370dda..0000000 --- a/src/v2_decoder.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_V2_DECODER_HPP_INCLUDED__ -#define __ZMQ_V2_DECODER_HPP_INCLUDED__ - -#include "decoder.hpp" - -namespace zmq -{ - // Decoder for ZMTP/2.x framing protocol. Converts data stream into messages. - class v2_decoder_t : public decoder_base_t <v2_decoder_t> - { - public: - - v2_decoder_t (size_t bufsize_, int64_t maxmsgsize_); - virtual ~v2_decoder_t (); - - // i_decoder interface. - virtual msg_t *msg () { return &in_progress; } - - private: - - int flags_ready (); - int one_byte_size_ready (); - int eight_byte_size_ready (); - int message_ready (); - - unsigned char tmpbuf [8]; - unsigned char msg_flags; - msg_t in_progress; - - const int64_t maxmsgsize; - - v2_decoder_t (const v2_decoder_t&); - void operator = (const v2_decoder_t&); - }; - -} - -#endif diff --git a/src/v2_encoder.cpp b/src/v2_encoder.cpp deleted file mode 100644 index d6c3613..0000000 --- a/src/v2_encoder.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "v2_protocol.hpp" -#include "v2_encoder.hpp" -#include "likely.hpp" -#include "wire.hpp" - -zmq::v2_encoder_t::v2_encoder_t (size_t bufsize_) : - encoder_base_t <v2_encoder_t> (bufsize_) -{ - // Write 0 bytes to the batch and go to message_ready state. - next_step (NULL, 0, &v2_encoder_t::message_ready, true); -} - -zmq::v2_encoder_t::~v2_encoder_t () -{ -} - -void zmq::v2_encoder_t::message_ready () -{ - // Encode flags. - unsigned char &protocol_flags = tmpbuf [0]; - protocol_flags = 0; - if (in_progress->flags () & msg_t::more) - protocol_flags |= v2_protocol_t::more_flag; - if (in_progress->size () > 255) - protocol_flags |= v2_protocol_t::large_flag; - if (in_progress->flags () & msg_t::command) - protocol_flags |= v2_protocol_t::command_flag; - - // Encode the message length. For messages less then 256 bytes, - // the length is encoded as 8-bit unsigned integer. For larger - // messages, 64-bit unsigned integer in network byte order is used. - const size_t size = in_progress->size (); - if (unlikely (size > 255)) { - put_uint64 (tmpbuf + 1, size); - next_step (tmpbuf, 9, &v2_encoder_t::size_ready, false); - } - else { - tmpbuf [1] = static_cast <uint8_t> (size); - next_step (tmpbuf, 2, &v2_encoder_t::size_ready, false); - } -} - -void zmq::v2_encoder_t::size_ready () -{ - // Write message body into the buffer. - next_step (in_progress->data (), in_progress->size (), - &v2_encoder_t::message_ready, true); -} diff --git a/src/v2_encoder.hpp b/src/v2_encoder.hpp deleted file mode 100644 index 12ec175..0000000 --- a/src/v2_encoder.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_V2_ENCODER_HPP_INCLUDED__ -#define __ZMQ_V2_ENCODER_HPP_INCLUDED__ - -#include "encoder.hpp" - -namespace zmq -{ - // Encoder for 0MQ framing protocol. Converts messages into data stream. - - class v2_encoder_t : public encoder_base_t <v2_encoder_t> - { - public: - - v2_encoder_t (size_t bufsize_); - virtual ~v2_encoder_t (); - - private: - - void size_ready (); - void message_ready (); - - unsigned char tmpbuf [9]; - - v2_encoder_t (const v2_encoder_t&); - const v2_encoder_t &operator = (const v2_encoder_t&); - }; -} - -#endif - diff --git a/src/v2_protocol.hpp b/src/v2_protocol.hpp deleted file mode 100644 index 308b293..0000000 --- a/src/v2_protocol.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_V2_PROTOCOL_HPP_INCLUDED__ -#define __ZMQ_V2_PROTOCOL_HPP_INCLUDED__ - -namespace zmq -{ - // Definition of constants for ZMTP/2.0 transport protocol. - class v2_protocol_t - { - public: - // Message flags. - enum - { - more_flag = 1, - large_flag = 2, - command_flag = 4 - }; - }; -} - -#endif diff --git a/src/windows.hpp b/src/windows.hpp deleted file mode 100755 index f54f735..0000000 --- a/src/windows.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_WINDOWS_HPP_INCLUDED__ -#define __ZMQ_WINDOWS_HPP_INCLUDED__ - -// The purpose of this header file is to turn on only the items actually -// needed on the windows platform. - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOGDICAPMASKS -#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ -#endif -#ifndef NOVIRTUALKEYCODES -#define NOVIRTUALKEYCODES // VK_* -#endif -#ifndef NOWINMESSAGES -#define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* -#endif -#ifndef NOWINSTYLES -#define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* -#endif -#ifndef NOSYSMETRICS -#define NOSYSMETRICS // SM_* -#endif -#ifndef NOMENUS -#define NOMENUS // MF_* -#endif -#ifndef NOICONS -#define NOICONS // IDI_* -#endif -#ifndef NOKEYSTATES -#define NOKEYSTATES // MK_* -#endif -#ifndef NOSYSCOMMANDS -#define NOSYSCOMMANDS // SC_* -#endif -#ifndef NORASTEROPS -#define NORASTEROPS // Binary and Tertiary raster ops -#endif -#ifndef NOSHOWWINDOW -#define NOSHOWWINDOW // SW_* -#endif -#ifndef OEMRESOURCE -#define OEMRESOURCE // OEM Resource values -#endif -#ifndef NOATOM -#define NOATOM // Atom Manager routines -#endif -#ifndef NOCLIPBOARD -#define NOCLIPBOARD // Clipboard routines -#endif -#ifndef NOCOLOR -#define NOCOLOR // Screen colors -#endif -#ifndef NOCTLMGR -#define NOCTLMGR // Control and Dialog routines -#endif -#ifndef NODRAWTEXT -#define NODRAWTEXT // DrawText() and DT_* -#endif -#ifndef NOGDI -#define NOGDI // All GDI defines and routines -#endif -#ifndef NOKERNEL -#define NOKERNEL // All KERNEL defines and routines -#endif -#ifndef NOUSER -#define NOUSER // All USER defines and routines -#endif -#ifndef NONLS -#define NONLS // All NLS defines and routines -#endif -#ifndef NOMB -#define NOMB // MB_* and MessageBox() -#endif -#ifndef NOMEMMGR -#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines -#endif -#ifndef NOMETAFILE -#define NOMETAFILE // typedef METAFILEPICT -#endif -#ifndef NOMINMAX -#define NOMINMAX // Macros min(a,b) and max(a,b) -#endif -#ifndef NOMSG -#define NOMSG // typedef MSG and associated routines -#endif -#ifndef NOOPENFILE -#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* -#endif -#ifndef NOSCROLL -#define NOSCROLL // SB_* and scrolling routines -#endif -#ifndef NOSERVICE -#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. -#endif -#ifndef NOSOUND -#define NOSOUND // Sound driver routines -#endif -#ifndef NOTEXTMETRIC -#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines -#endif -#ifndef NOWH -#define NOWH // SetWindowsHook and WH_* -#endif -#ifndef NOWINOFFSETS -#define NOWINOFFSETS // GWL_*, GCL_*, associated routines -#endif -#ifndef NOCOMM -#define NOCOMM // COMM driver routines -#endif -#ifndef NOKANJI -#define NOKANJI // Kanji support stuff. -#endif -#ifndef NOHELP -#define NOHELP // Help engine interface. -#endif -#ifndef NOPROFILER -#define NOPROFILER // Profiler interface. -#endif -#ifndef NODEFERWINDOWPOS -#define NODEFERWINDOWPOS // DeferWindowPos routines -#endif -#ifndef NOMCX -#define NOMCX // Modem Configuration ExtensionsA -#endif - -// Set target version to Windows Server 2003, Windows XP/SP1 or higher. -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include <windows.h> - -#ifdef __MINGW32__ -// Require Windows XP or higher with MinGW for getaddrinfo(). -#if(_WIN32_WINNT >= 0x0501) -#else -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#endif - -#include <winsock2.h> -#include <mswsock.h> -#include <Mstcpip.h> - -#include <ws2tcpip.h> -#include <ipexport.h> -#if !defined _WIN32_WCE -#include <process.h> -#endif - -// In MinGW environment AI_NUMERICSERV is not defined. -#ifndef AI_NUMERICSERV -#define AI_NUMERICSERV 0x0400 -#endif -#endif diff --git a/src/wire.hpp b/src/wire.hpp deleted file mode 100644 index 7aec7b8..0000000 --- a/src/wire.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_WIRE_HPP_INCLUDED__ -#define __ZMQ_WIRE_HPP_INCLUDED__ - -#include "stdint.hpp" - -namespace zmq -{ - - // Helper functions to convert different integer types to/from network - // byte order. - - inline void put_uint8 (unsigned char *buffer_, uint8_t value) - { - *buffer_ = value; - } - - inline uint8_t get_uint8 (const unsigned char *buffer_) - { - return *buffer_; - } - - inline void put_uint16 (unsigned char *buffer_, uint16_t value) - { - buffer_ [0] = (unsigned char) (((value) >> 8) & 0xff); - buffer_ [1] = (unsigned char) (value & 0xff); - } - - inline uint16_t get_uint16 (const unsigned char *buffer_) - { - return - (((uint16_t) buffer_ [0]) << 8) | - ((uint16_t) buffer_ [1]); - } - - inline void put_uint32 (unsigned char *buffer_, uint32_t value) - { - buffer_ [0] = (unsigned char) (((value) >> 24) & 0xff); - buffer_ [1] = (unsigned char) (((value) >> 16) & 0xff); - buffer_ [2] = (unsigned char) (((value) >> 8) & 0xff); - buffer_ [3] = (unsigned char) (value & 0xff); - } - - inline uint32_t get_uint32 (const unsigned char *buffer_) - { - return - (((uint32_t) buffer_ [0]) << 24) | - (((uint32_t) buffer_ [1]) << 16) | - (((uint32_t) buffer_ [2]) << 8) | - ((uint32_t) buffer_ [3]); - } - - inline void put_uint64 (unsigned char *buffer_, uint64_t value) - { - buffer_ [0] = (unsigned char) (((value) >> 56) & 0xff); - buffer_ [1] = (unsigned char) (((value) >> 48) & 0xff); - buffer_ [2] = (unsigned char) (((value) >> 40) & 0xff); - buffer_ [3] = (unsigned char) (((value) >> 32) & 0xff); - buffer_ [4] = (unsigned char) (((value) >> 24) & 0xff); - buffer_ [5] = (unsigned char) (((value) >> 16) & 0xff); - buffer_ [6] = (unsigned char) (((value) >> 8) & 0xff); - buffer_ [7] = (unsigned char) (value & 0xff); - } - - inline uint64_t get_uint64 (const unsigned char *buffer_) - { - return - (((uint64_t) buffer_ [0]) << 56) | - (((uint64_t) buffer_ [1]) << 48) | - (((uint64_t) buffer_ [2]) << 40) | - (((uint64_t) buffer_ [3]) << 32) | - (((uint64_t) buffer_ [4]) << 24) | - (((uint64_t) buffer_ [5]) << 16) | - (((uint64_t) buffer_ [6]) << 8) | - ((uint64_t) buffer_ [7]); - } - -} - -#endif diff --git a/src/xpub.cpp b/src/xpub.cpp deleted file mode 100644 index 99a699d..0000000 --- a/src/xpub.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> - -#include "xpub.hpp" -#include "pipe.hpp" -#include "err.hpp" -#include "msg.hpp" - -zmq::xpub_t::xpub_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - verbose(false), - more (false) -{ - options.type = ZMQ_XPUB; -} - -zmq::xpub_t::~xpub_t () -{ -} - -void zmq::xpub_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - zmq_assert (pipe_); - dist.attach (pipe_); - - // If subscribe_to_all_ is specified, the caller would like to subscribe - // to all data on this pipe, implicitly. - if (subscribe_to_all_) - subscriptions.add (NULL, 0, pipe_); - - // The pipe is active when attached. Let's read the subscriptions from - // it, if any. - xread_activated (pipe_); -} - -void zmq::xpub_t::xread_activated (pipe_t *pipe_) -{ - // There are some subscriptions waiting. Let's process them. - msg_t sub; - while (pipe_->read (&sub)) { - // Apply the subscription to the trie - unsigned char *const data = (unsigned char *) sub.data (); - const size_t size = sub.size (); - if (size > 0 && (*data == 0 || *data == 1)) { - bool unique; - if (*data == 0) - unique = subscriptions.rm (data + 1, size - 1, pipe_); - else - unique = 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. (Unsubscribe is not verbose.) - if (options.type == ZMQ_XPUB && (unique || (*data && verbose))) { - pending_data.push_back (blob_t (data, size)); - pending_flags.push_back (0); - } - } - else { - // Process user message coming upstream from xsub socket - pending_data.push_back (blob_t (data, size)); - pending_flags.push_back (sub.flags ()); - } - sub.close (); - } -} - -void zmq::xpub_t::xwrite_activated (pipe_t *pipe_) -{ - dist.activated (pipe_); -} - -int zmq::xpub_t::xsetsockopt (int option_, const void *optval_, - size_t optvallen_) -{ - if (option_ != ZMQ_XPUB_VERBOSE) { - errno = EINVAL; - return -1; - } - if (optvallen_ != sizeof (int) || *static_cast <const int*> (optval_) < 0) { - errno = EINVAL; - return -1; - } - verbose = (*static_cast <const int*> (optval_) != 0); - return 0; -} - -void zmq::xpub_t::xpipe_terminated (pipe_t *pipe_) -{ - // Remove the pipe from the trie. If there are topics that nobody - // is interested in anymore, send corresponding unsubscriptions - // upstream. - subscriptions.rm (pipe_, send_unsubscription, this); - - dist.pipe_terminated (pipe_); -} - -void zmq::xpub_t::mark_as_matching (pipe_t *pipe_, void *arg_) -{ - xpub_t *self = (xpub_t*) arg_; - self->dist.match (pipe_); -} - -int zmq::xpub_t::xsend (msg_t *msg_) -{ - bool msg_more = msg_->flags () & msg_t::more ? true : false; - - // For the first part of multi-part message, find the matching pipes. - if (!more) - subscriptions.match ((unsigned char*) msg_->data (), msg_->size (), - mark_as_matching, this); - - // Send the message to all the pipes that were marked as matching - // in the previous step. - int rc = dist.send_to_matching (msg_); - if (rc != 0) - return rc; - - // If we are at the end of multi-part message we can mark all the pipes - // as non-matching. - if (!msg_more) - dist.unmatch (); - - more = msg_more; - - return 0; -} - -bool zmq::xpub_t::xhas_out () -{ - return dist.has_out (); -} - -int zmq::xpub_t::xrecv (msg_t *msg_) -{ - // If there is at least one - if (pending_data.empty ()) { - errno = EAGAIN; - return -1; - } - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init_size (pending_data.front ().size ()); - errno_assert (rc == 0); - memcpy (msg_->data (), - pending_data.front ().data (), - pending_data.front ().size ()); - msg_->set_flags (pending_flags.front ()); - pending_data.pop_front (); - pending_flags.pop_front (); - return 0; -} - -bool zmq::xpub_t::xhas_in () -{ - return !pending_data.empty (); -} - -void zmq::xpub_t::send_unsubscription (unsigned char *data_, size_t size_, - void *arg_) -{ - xpub_t *self = (xpub_t*) arg_; - - if (self->options.type != ZMQ_PUB) { - // Place the unsubscription to the queue of pending (un)sunscriptions - // to be retrived by the user later on. - blob_t unsub (size_ + 1, 0); - unsub [0] = 0; - memcpy (&unsub [1], data_, size_); - self->pending_data.push_back (unsub); - self->pending_flags.push_back (0); - } -} diff --git a/src/xpub.hpp b/src/xpub.hpp deleted file mode 100644 index 362425a..0000000 --- a/src/xpub.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_XPUB_HPP_INCLUDED__ -#define __ZMQ_XPUB_HPP_INCLUDED__ - -#include <deque> -#include <string> - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "mtrie.hpp" -#include "array.hpp" -#include "dist.hpp" - -namespace zmq -{ - - class ctx_t; - class msg_t; - class pipe_t; - class io_thread_t; - - class xpub_t : - public socket_base_t - { - public: - - xpub_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~xpub_t (); - - // Implementations of virtual functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_ = false); - int xsend (zmq::msg_t *msg_); - bool xhas_out (); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - int xsetsockopt (int option_, const void *optval_, size_t optvallen_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - - // Function to be applied to the trie to send all the subsciptions - // upstream. - static void send_unsubscription (unsigned char *data_, size_t size_, - void *arg_); - - // Function to be applied to each matching pipes. - static void mark_as_matching (zmq::pipe_t *pipe_, void *arg_); - - // List of all subscriptions mapped to corresponding pipes. - mtrie_t subscriptions; - - // Distributor of messages holding the list of outbound pipes. - dist_t dist; - - // If true, send all subscription messages upstream, not just - // unique ones - bool verbose; - - // True if we are in the middle of sending a multi-part message. - bool more; - - // List of pending (un)subscriptions, ie. those that were already - // applied to the trie, but not yet received by the user. - typedef std::basic_string <unsigned char> blob_t; - std::deque <blob_t> pending_data; - std::deque <unsigned char> pending_flags; - - xpub_t (const xpub_t&); - const xpub_t &operator = (const xpub_t&); - }; - -} - -#endif diff --git a/src/xsub.cpp b/src/xsub.cpp deleted file mode 100644 index c4381a2..0000000 --- a/src/xsub.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> - -#include "xsub.hpp" -#include "err.hpp" - -zmq::xsub_t::xsub_t (class ctx_t *parent_, uint32_t tid_, int sid_) : - socket_base_t (parent_, tid_, sid_), - has_message (false), - more (false) -{ - options.type = ZMQ_XSUB; - - // When socket is being closed down we don't want to wait till pending - // subscription commands are sent to the wire. - options.linger = 0; - - int rc = message.init (); - errno_assert (rc == 0); -} - -zmq::xsub_t::~xsub_t () -{ - int rc = message.close (); - errno_assert (rc == 0); -} - -void zmq::xsub_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) -{ - // subscribe_to_all_ is unused - (void) subscribe_to_all_; - - zmq_assert (pipe_); - fq.attach (pipe_); - dist.attach (pipe_); - - // Send all the cached subscriptions to the new upstream peer. - subscriptions.apply (send_subscription, pipe_); - pipe_->flush (); -} - -void zmq::xsub_t::xread_activated (pipe_t *pipe_) -{ - fq.activated (pipe_); -} - -void zmq::xsub_t::xwrite_activated (pipe_t *pipe_) -{ - dist.activated (pipe_); -} - -void zmq::xsub_t::xpipe_terminated (pipe_t *pipe_) -{ - fq.pipe_terminated (pipe_); - dist.pipe_terminated (pipe_); -} - -void zmq::xsub_t::xhiccuped (pipe_t *pipe_) -{ - // Send all the cached subscriptions to the hiccuped pipe. - subscriptions.apply (send_subscription, pipe_); - pipe_->flush (); -} - -int zmq::xsub_t::xsend (msg_t *msg_) -{ - size_t size = msg_->size (); - unsigned char *data = (unsigned char *) msg_->data (); - - if (size > 0 && *data == 1) { - // Process subscribe message - // This used to filter out duplicate subscriptions, - // however this is alread done on the XPUB side and - // doing it here as well breaks ZMQ_XPUB_VERBOSE - // when there are forwarding devices involved. - subscriptions.add (data + 1, size - 1); - return dist.send_to_all (msg_); - } - else - if (size > 0 && *data == 0) { - // Process unsubscribe message - if (subscriptions.rm (data + 1, size - 1)) - return dist.send_to_all (msg_); - } - else - // User message sent upstream to XPUB socket - return dist.send_to_all (msg_); - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - - return 0; -} - -bool zmq::xsub_t::xhas_out () -{ - // Subscription can be added/removed anytime. - return true; -} - -int zmq::xsub_t::xrecv (msg_t *msg_) -{ - // If there's already a message prepared by a previous call to zmq_poll, - // return it straight ahead. - if (has_message) { - int rc = msg_->move (message); - errno_assert (rc == 0); - has_message = false; - more = msg_->flags () & msg_t::more ? true : false; - return 0; - } - - // TODO: This can result in infinite loop in the case of continuous - // stream of non-matching messages which breaks the non-blocking recv - // semantics. - while (true) { - - // Get a message using fair queueing algorithm. - int rc = fq.recv (msg_); - - // If there's no message available, return immediately. - // The same when error occurs. - if (rc != 0) - return -1; - - // Check whether the message matches at least one subscription. - // Non-initial parts of the message are passed - if (more || !options.filter || match (msg_)) { - more = msg_->flags () & msg_t::more ? true : false; - return 0; - } - - // Message doesn't match. Pop any remaining parts of the message - // from the pipe. - while (msg_->flags () & msg_t::more) { - rc = fq.recv (msg_); - errno_assert (rc == 0); - } - } -} - -bool zmq::xsub_t::xhas_in () -{ - // There are subsequent parts of the partly-read message available. - if (more) - return true; - - // If there's already a message prepared by a previous call to zmq_poll, - // return straight ahead. - if (has_message) - return true; - - // TODO: This can result in infinite loop in the case of continuous - // stream of non-matching messages. - while (true) { - - // Get a message using fair queueing algorithm. - int rc = fq.recv (&message); - - // If there's no message available, return immediately. - // The same when error occurs. - if (rc != 0) { - errno_assert (errno == EAGAIN); - return false; - } - - // Check whether the message matches at least one subscription. - if (!options.filter || match (&message)) { - has_message = true; - return true; - } - - // Message doesn't match. Pop any remaining parts of the message - // from the pipe. - while (message.flags () & msg_t::more) { - rc = fq.recv (&message); - errno_assert (rc == 0); - } - } -} - -bool zmq::xsub_t::match (msg_t *msg_) -{ - return subscriptions.check ((unsigned char*) msg_->data (), msg_->size ()); -} - -void zmq::xsub_t::send_subscription (unsigned char *data_, size_t size_, - void *arg_) -{ - pipe_t *pipe = (pipe_t*) arg_; - - // Create the subsctription message. - msg_t msg; - int rc = msg.init_size (size_ + 1); - errno_assert (rc == 0); - unsigned char *data = (unsigned char*) msg.data (); - data [0] = 1; - memcpy (data + 1, data_, size_); - - // Send it to the pipe. - bool sent = pipe->write (&msg); - // If we reached the SNDHWM, and thus cannot send the subscription, drop - // the subscription message instead. This matches the behaviour of - // zmq_setsockopt(ZMQ_SUBSCRIBE, ...), which also drops subscriptions - // when the SNDHWM is reached. - if (!sent) - msg.close (); -} diff --git a/src/xsub.hpp b/src/xsub.hpp deleted file mode 100644 index af7d0c9..0000000 --- a/src/xsub.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_XSUB_HPP_INCLUDED__ -#define __ZMQ_XSUB_HPP_INCLUDED__ - -#include "socket_base.hpp" -#include "session_base.hpp" -#include "dist.hpp" -#include "fq.hpp" -#include "trie.hpp" - -namespace zmq -{ - - class ctx_t; - class pipe_t; - class io_thread_t; - - class xsub_t : - public socket_base_t - { - public: - - xsub_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_); - ~xsub_t (); - - protected: - - // Overloads of functions from socket_base_t. - void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_); - int xsend (zmq::msg_t *msg_); - bool xhas_out (); - int xrecv (zmq::msg_t *msg_); - bool xhas_in (); - void xread_activated (zmq::pipe_t *pipe_); - void xwrite_activated (zmq::pipe_t *pipe_); - void xhiccuped (pipe_t *pipe_); - void xpipe_terminated (zmq::pipe_t *pipe_); - - private: - - // Check whether the message matches at least one subscription. - bool match (zmq::msg_t *msg_); - - // Function to be applied to the trie to send all the subsciptions - // upstream. - static void send_subscription (unsigned char *data_, size_t size_, - void *arg_); - - // Fair queueing object for inbound pipes. - fq_t fq; - - // Object for distributing the subscriptions upstream. - dist_t dist; - - // The repository of subscriptions. - trie_t subscriptions; - - // If true, 'message' contains a matching message to return on the - // next recv call. - bool has_message; - msg_t message; - - // If true, part of a multipart message was already received, but - // there are following parts still waiting. - bool more; - - xsub_t (const xsub_t&); - const xsub_t &operator = (const xsub_t&); - }; - -} - -#endif - diff --git a/src/ypipe.hpp b/src/ypipe.hpp deleted file mode 100644 index 86e5d01..0000000 --- a/src/ypipe.hpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_YPIPE_HPP_INCLUDED__ -#define __ZMQ_YPIPE_HPP_INCLUDED__ - -#include "atomic_ptr.hpp" -#include "yqueue.hpp" -#include "platform.hpp" -#include "ypipe_base.hpp" - -namespace zmq -{ - - // Lock-free queue implementation. - // Only a single thread can read from the pipe at any specific moment. - // Only a single thread can write to the pipe at any specific moment. - // T is the type of the object in the queue. - // N is granularity of the pipe, i.e. how many items are needed to - // perform next memory allocation. - - template <typename T, int N> class ypipe_t : public ypipe_base_t<T,N> - { - public: - - // Initialises the pipe. - inline ypipe_t () - { - // Insert terminator element into the queue. - queue.push (); - - // Let all the pointers to point to the terminator. - // (unless pipe is dead, in which case c is set to NULL). - r = w = f = &queue.back (); - c.set (&queue.back ()); - } - - // The destructor doesn't have to be virtual. It is mad virtual - // just to keep ICC and code checking tools from complaining. - inline virtual ~ypipe_t () - { - } - - // Following function (write) deliberately copies uninitialised data - // when used with zmq_msg. Initialising the VSM body for - // non-VSM messages won't be good for performance. - -#ifdef ZMQ_HAVE_OPENVMS -#pragma message save -#pragma message disable(UNINIT) -#endif - - // Write an item to the pipe. Don't flush it yet. If incomplete is - // set to true the item is assumed to be continued by items - // subsequently written to the pipe. Incomplete items are never - // flushed down the stream. - inline void write (const T &value_, bool incomplete_) - { - // Place the value to the queue, add new terminator element. - queue.back () = value_; - queue.push (); - - // Move the "flush up to here" poiter. - if (!incomplete_) - f = &queue.back (); - } - -#ifdef ZMQ_HAVE_OPENVMS -#pragma message restore -#endif - - // Pop an incomplete item from the pipe. Returns true is such - // item exists, false otherwise. - inline bool unwrite (T *value_) - { - if (f == &queue.back ()) - return false; - queue.unpush (); - *value_ = queue.back (); - return true; - } - - // Flush all the completed items into the pipe. Returns false if - // the reader thread is sleeping. In that case, caller is obliged to - // wake the reader up before using the pipe again. - inline bool flush () - { - // If there are no un-flushed items, do nothing. - if (w == f) - return true; - - // Try to set 'c' to 'f'. - if (c.cas (w, f) != w) { - - // Compare-and-swap was unseccessful because 'c' is NULL. - // This means that the reader is asleep. Therefore we don't - // care about thread-safeness and update c in non-atomic - // manner. We'll return false to let the caller know - // that reader is sleeping. - c.set (f); - w = f; - return false; - } - - // Reader is alive. Nothing special to do now. Just move - // the 'first un-flushed item' pointer to 'f'. - w = f; - return true; - } - - // Check whether item is available for reading. - inline bool check_read () - { - // Was the value prefetched already? If so, return. - if (&queue.front () != r && r) - return true; - - // There's no prefetched value, so let us prefetch more values. - // Prefetching is to simply retrieve the - // pointer from c in atomic fashion. If there are no - // items to prefetch, set c to NULL (using compare-and-swap). - r = c.cas (&queue.front (), NULL); - - // If there are no elements prefetched, exit. - // During pipe's lifetime r should never be NULL, however, - // it can happen during pipe shutdown when items - // are being deallocated. - if (&queue.front () == r || !r) - return false; - - // There was at least one value prefetched. - return true; - } - - // Reads an item from the pipe. Returns false if there is no value. - // available. - inline bool read (T *value_) - { - // Try to prefetch a value. - if (!check_read ()) - return false; - - // There was at least one value prefetched. - // Return it to the caller. - *value_ = queue.front (); - queue.pop (); - return true; - } - - // Applies the function fn to the first elemenent in the pipe - // and returns the value returned by the fn. - // The pipe mustn't be empty or the function crashes. - inline bool probe (bool (*fn)(T &)) - { - bool rc = check_read (); - zmq_assert (rc); - - return (*fn) (queue.front ()); - } - - protected: - - // Allocation-efficient queue to store pipe items. - // Front of the queue points to the first prefetched item, back of - // the pipe points to last un-flushed item. Front is used only by - // reader thread, while back is used only by writer thread. - yqueue_t <T, N> queue; - - // Points to the first un-flushed item. This variable is used - // exclusively by writer thread. - T *w; - - // Points to the first un-prefetched item. This variable is used - // exclusively by reader thread. - T *r; - - // Points to the first item to be flushed in the future. - T *f; - - // The single point of contention between writer and reader thread. - // Points past the last flushed item. If it is NULL, - // reader is asleep. This pointer should be always accessed using - // atomic operations. - atomic_ptr_t <T> c; - - // Disable copying of ypipe object. - ypipe_t (const ypipe_t&); - const ypipe_t &operator = (const ypipe_t&); - }; - -} - -#endif diff --git a/src/ypipe_base.hpp b/src/ypipe_base.hpp deleted file mode 100644 index b7e7081..0000000 --- a/src/ypipe_base.hpp +++ /dev/null @@ -1,44 +0,0 @@ - -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_YPIPE_BASE_HPP_INCLUDED__ -#define __ZMQ_YPIPE_BASE_HPP_INCLUDED__ - - -namespace zmq -{ - // ypipe_base abstracts ypipe and ypipe_conflate specific - // classes, one is selected according to a the conflate - // socket option - - template <typename T, int N> class ypipe_base_t - { - public: - virtual ~ypipe_base_t () {} - virtual void write (const T &value_, bool incomplete_) = 0; - virtual bool unwrite (T *value_) = 0; - virtual bool flush () = 0; - virtual bool check_read () = 0; - virtual bool read (T *value_) = 0; - virtual bool probe (bool (*fn)(T &)) = 0; - }; -} - -#endif diff --git a/src/ypipe_conflate.hpp b/src/ypipe_conflate.hpp deleted file mode 100644 index 6dc20ef..0000000 --- a/src/ypipe_conflate.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_YPIPE_CONFLATE_HPP_INCLUDED__ -#define __ZMQ_YPIPE_CONFLATE_HPP_INCLUDED__ - -#include "platform.hpp" -#include "dbuffer.hpp" -#include "ypipe_base.hpp" - -namespace zmq -{ - - // Adapter for dbuffer, to plug it in instead of a queue for the sake - // of implementing the conflate socket option, which, if set, makes - // the receiving side to discard all incoming messages but the last one. - // - // reader_awake flag is needed here to mimic ypipe delicate behaviour - // around the reader being asleep (see 'c' pointer being NULL in ypipe.hpp) - - template <typename T, int N> class ypipe_conflate_t : public ypipe_base_t<T,N> - { - public: - - // Initialises the pipe. - inline ypipe_conflate_t () - : reader_awake(false) - { - } - - // The destructor doesn't have to be virtual. It is mad virtual - // just to keep ICC and code checking tools from complaining. - inline virtual ~ypipe_conflate_t () - { - } - - // Following function (write) deliberately copies uninitialised data - // when used with zmq_msg. Initialising the VSM body for - // non-VSM messages won't be good for performance. - -#ifdef ZMQ_HAVE_OPENVMS -#pragma message save -#pragma message disable(UNINIT) -#endif - inline void write (const T &value_, bool incomplete_) - { - (void)incomplete_; - - dbuffer.write (value_); - } - -#ifdef ZMQ_HAVE_OPENVMS -#pragma message restore -#endif - - // There are no incomplete items for conflate ypipe - inline bool unwrite (T *value_) - { - return false; - } - - // Flush is no-op for conflate ypipe. Reader asleep behaviour - // is as of the usual ypipe. - // Returns false if the reader thread is sleeping. In that case, - // caller is obliged to wake the reader up before using the pipe again. - inline bool flush () - { - return reader_awake; - } - - // Check whether item is available for reading. - inline bool check_read () - { - bool res = dbuffer.check_read (); - if (!res) - reader_awake = false; - - return res; - } - - // Reads an item from the pipe. Returns false if there is no value. - // available. - inline bool read (T *value_) - { - if (!check_read ()) - return false; - - return dbuffer.read (value_); - } - - // Applies the function fn to the first elemenent in the pipe - // and returns the value returned by the fn. - // The pipe mustn't be empty or the function crashes. - inline bool probe (bool (*fn)(T &)) - { - return dbuffer.probe (fn); - } - - protected: - - dbuffer_t <T> dbuffer; - bool reader_awake; - - // Disable copying of ypipe object. - ypipe_conflate_t (const ypipe_conflate_t&); - const ypipe_conflate_t &operator = (const ypipe_conflate_t&); - }; - -} - -#endif diff --git a/src/yqueue.hpp b/src/yqueue.hpp deleted file mode 100644 index 56046da..0000000 --- a/src/yqueue.hpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ZMQ_YQUEUE_HPP_INCLUDED__ -#define __ZMQ_YQUEUE_HPP_INCLUDED__ - -#include <stdlib.h> -#include <stddef.h> - -#include "err.hpp" -#include "atomic_ptr.hpp" - -namespace zmq -{ - - // yqueue is an efficient queue implementation. The main goal is - // to minimise number of allocations/deallocations needed. Thus yqueue - // allocates/deallocates elements in batches of N. - // - // yqueue allows one thread to use push/back function and another one - // to use pop/front functions. However, user must ensure that there's no - // pop on the empty queue and that both threads don't access the same - // element in unsynchronised manner. - // - // T is the type of the object in the queue. - // N is granularity of the queue (how many pushes have to be done till - // actual memory allocation is required). - - template <typename T, int N> class yqueue_t - { - public: - - // Create the queue. - inline yqueue_t () - { - begin_chunk = (chunk_t*) malloc (sizeof (chunk_t)); - alloc_assert (begin_chunk); - begin_pos = 0; - back_chunk = NULL; - back_pos = 0; - end_chunk = begin_chunk; - end_pos = 0; - } - - // Destroy the queue. - inline ~yqueue_t () - { - while (true) { - if (begin_chunk == end_chunk) { - free (begin_chunk); - break; - } - chunk_t *o = begin_chunk; - begin_chunk = begin_chunk->next; - free (o); - } - - chunk_t *sc = spare_chunk.xchg (NULL); - free (sc); - } - - // Returns reference to the front element of the queue. - // If the queue is empty, behaviour is undefined. - inline T &front () - { - return begin_chunk->values [begin_pos]; - } - - // Returns reference to the back element of the queue. - // If the queue is empty, behaviour is undefined. - inline T &back () - { - return back_chunk->values [back_pos]; - } - - // Adds an element to the back end of the queue. - inline void push () - { - back_chunk = end_chunk; - back_pos = end_pos; - - if (++end_pos != N) - return; - - chunk_t *sc = spare_chunk.xchg (NULL); - if (sc) { - end_chunk->next = sc; - sc->prev = end_chunk; - } else { - end_chunk->next = (chunk_t*) malloc (sizeof (chunk_t)); - alloc_assert (end_chunk->next); - end_chunk->next->prev = end_chunk; - } - end_chunk = end_chunk->next; - end_pos = 0; - } - - // Removes element from the back end of the queue. In other words - // it rollbacks last push to the queue. Take care: Caller is - // responsible for destroying the object being unpushed. - // The caller must also guarantee that the queue isn't empty when - // unpush is called. It cannot be done automatically as the read - // side of the queue can be managed by different, completely - // unsynchronised thread. - inline void unpush () - { - // First, move 'back' one position backwards. - if (back_pos) - --back_pos; - else { - back_pos = N - 1; - back_chunk = back_chunk->prev; - } - - // Now, move 'end' position backwards. Note that obsolete end chunk - // is not used as a spare chunk. The analysis shows that doing so - // would require free and atomic operation per chunk deallocated - // instead of a simple free. - if (end_pos) - --end_pos; - else { - end_pos = N - 1; - end_chunk = end_chunk->prev; - free (end_chunk->next); - end_chunk->next = NULL; - } - } - - // Removes an element from the front end of the queue. - inline void pop () - { - if (++ begin_pos == N) { - chunk_t *o = begin_chunk; - begin_chunk = begin_chunk->next; - begin_chunk->prev = NULL; - begin_pos = 0; - - // 'o' has been more recently used than spare_chunk, - // so for cache reasons we'll get rid of the spare and - // use 'o' as the spare. - chunk_t *cs = spare_chunk.xchg (o); - free (cs); - } - } - - private: - - // Individual memory chunk to hold N elements. - struct chunk_t - { - T values [N]; - chunk_t *prev; - chunk_t *next; - }; - - // Back position may point to invalid memory if the queue is empty, - // while begin & end positions are always valid. Begin position is - // accessed exclusively be queue reader (front/pop), while back and - // end positions are accessed exclusively by queue writer (back/push). - chunk_t *begin_chunk; - int begin_pos; - chunk_t *back_chunk; - int back_pos; - chunk_t *end_chunk; - int end_pos; - - // People are likely to produce and consume at similar rates. In - // this scenario holding onto the most recently freed chunk saves - // us from having to call malloc/free. - atomic_ptr_t<chunk_t> spare_chunk; - - // Disable copying of yqueue. - yqueue_t (const yqueue_t&); - const yqueue_t &operator = (const yqueue_t&); - }; - -} - -#endif diff --git a/src/zmq.cpp b/src/zmq.cpp deleted file mode 100644 index d911628..0000000 --- a/src/zmq.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#define ZMQ_TYPE_UNSAFE - -#include "platform.hpp" - -#if defined ZMQ_FORCE_SELECT -#define ZMQ_POLL_BASED_ON_SELECT -#elif defined ZMQ_FORCE_POLL -#define ZMQ_POLL_BASED_ON_POLL -#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\ - defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\ - defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\ - defined ZMQ_HAVE_NETBSD -#define ZMQ_POLL_BASED_ON_POLL -#elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS ||\ - defined ZMQ_HAVE_CYGWIN -#define ZMQ_POLL_BASED_ON_SELECT -#endif - -// On AIX platform, poll.h has to be included first to get consistent -// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents' -// instead of 'events' and 'revents' and defines macros to map from POSIX-y -// names to AIX-specific names). -#if defined ZMQ_POLL_BASED_ON_POLL -#include <poll.h> -#endif - -// zmq.h must be included *after* poll.h for AIX to build properly -#include "../include/zmq.h" - -#if defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#else -#include <unistd.h> -#endif - - -// XSI vector I/O -#if defined ZMQ_HAVE_UIO -#include <sys/uio.h> -#else -struct iovec { - void *iov_base; - size_t iov_len; -}; -#endif - - -#include <string.h> -#include <stdlib.h> -#include <new> - -#include "proxy.hpp" -#include "socket_base.hpp" -#include "stdint.hpp" -#include "config.hpp" -#include "likely.hpp" -#include "clock.hpp" -#include "ctx.hpp" -#include "err.hpp" -#include "msg.hpp" -#include "fd.hpp" - -#if !defined ZMQ_HAVE_WINDOWS -#include <unistd.h> -#endif - -#if defined ZMQ_HAVE_OPENPGM -#define __PGM_WININT_H__ -#include <pgm/pgm.h> -#endif - -// Compile time check whether msg_t fits into zmq_msg_t. -typedef char check_msg_t_size - [sizeof (zmq::msg_t) == sizeof (zmq_msg_t) ? 1 : -1]; - - -void zmq_version (int *major_, int *minor_, int *patch_) -{ - *major_ = ZMQ_VERSION_MAJOR; - *minor_ = ZMQ_VERSION_MINOR; - *patch_ = ZMQ_VERSION_PATCH; -} - - -const char *zmq_strerror (int errnum_) -{ - return zmq::errno_to_string (errnum_); -} - -int zmq_errno (void) -{ - return errno; -} - - -// New context API - -void *zmq_ctx_new (void) -{ -#if defined ZMQ_HAVE_OPENPGM - - // Init PGM transport. Ensure threading and timer are enabled. Find PGM - // protocol ID. Note that if you want to use gettimeofday and sleep for - // openPGM timing, set environment variables PGM_TIMER to "GTOD" and - // PGM_SLEEP to "USLEEP". - pgm_error_t *pgm_error = NULL; - const bool ok = pgm_init (&pgm_error); - if (ok != TRUE) { - - // Invalid parameters don't set pgm_error_t - zmq_assert (pgm_error != NULL); - if (pgm_error->domain == PGM_ERROR_DOMAIN_TIME && ( - pgm_error->code == PGM_ERROR_FAILED)) { - - // Failed to access RTC or HPET device. - pgm_error_free (pgm_error); - errno = EINVAL; - return NULL; - } - - // PGM_ERROR_DOMAIN_ENGINE: WSAStartup errors or missing WSARecvMsg. - zmq_assert (false); - } -#endif - -#ifdef ZMQ_HAVE_WINDOWS - // Intialise Windows sockets. Note that WSAStartup can be called multiple - // times given that WSACleanup will be called for each WSAStartup. - // We do this before the ctx constructor since its embedded mailbox_t - // object needs Winsock to be up and running. - WORD version_requested = MAKEWORD (2, 2); - WSADATA wsa_data; - int rc = WSAStartup (version_requested, &wsa_data); - zmq_assert (rc == 0); - zmq_assert (LOBYTE (wsa_data.wVersion) == 2 && - HIBYTE (wsa_data.wVersion) == 2); -#endif - - // Create 0MQ context. - zmq::ctx_t *ctx = new (std::nothrow) zmq::ctx_t; - alloc_assert (ctx); - return ctx; -} - -int zmq_ctx_term (void *ctx_) -{ - if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { - errno = EFAULT; - return -1; - } - - int rc = ((zmq::ctx_t*) ctx_)->terminate (); - int en = errno; - - // Shut down only if termination was not interrupted by a signal. - if (!rc || en != EINTR) { -#ifdef ZMQ_HAVE_WINDOWS - // On Windows, uninitialise socket layer. - rc = WSACleanup (); - wsa_assert (rc != SOCKET_ERROR); -#endif - -#if defined ZMQ_HAVE_OPENPGM - // Shut down the OpenPGM library. - if (pgm_shutdown () != TRUE) - zmq_assert (false); -#endif - } - - errno = en; - return rc; -} - -int zmq_ctx_shutdown (void *ctx_) -{ - if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { - errno = EFAULT; - return -1; - } - - return ((zmq::ctx_t*) ctx_)->shutdown (); -} - -int zmq_ctx_set (void *ctx_, int option_, int optval_) -{ - if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { - errno = EFAULT; - return -1; - } - return ((zmq::ctx_t*) ctx_)->set (option_, optval_); -} - -int zmq_ctx_get (void *ctx_, int option_) -{ - if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { - errno = EFAULT; - return -1; - } - return ((zmq::ctx_t*) ctx_)->get (option_); -} - -// Stable/legacy context API - -void *zmq_init (int io_threads_) -{ - if (io_threads_ >= 0) { - void *ctx = zmq_ctx_new (); - zmq_ctx_set (ctx, ZMQ_IO_THREADS, io_threads_); - return ctx; - } - errno = EINVAL; - return NULL; -} - -int zmq_term (void *ctx_) -{ - return zmq_ctx_term (ctx_); -} - -int zmq_ctx_destroy (void *ctx_) -{ - return zmq_ctx_term (ctx_); -} - - -// Sockets - -void *zmq_socket (void *ctx_, int type_) -{ - if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { - errno = EFAULT; - return NULL; - } - zmq::ctx_t *ctx = (zmq::ctx_t*) ctx_; - zmq::socket_base_t *s = ctx->create_socket (type_); - return (void *) s; -} - -int zmq_close (void *s_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - ((zmq::socket_base_t*) s_)->close (); - return 0; -} - -int zmq_setsockopt (void *s_, int option_, const void *optval_, - size_t optvallen_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s->setsockopt (option_, optval_, optvallen_); - return result; -} - -int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s->getsockopt (option_, optval_, optvallen_); - return result; -} - -int zmq_socket_monitor (void *s_, const char *addr_, int events_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s->monitor (addr_, events_); - return result; -} - -int zmq_bind (void *s_, const char *addr_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s->bind (addr_); - return result; -} - -int zmq_connect (void *s_, const char *addr_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s->connect (addr_); - return result; -} - -int zmq_unbind (void *s_, const char *addr_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - return s->term_endpoint (addr_); -} - -int zmq_disconnect (void *s_, const char *addr_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - return s->term_endpoint (addr_); -} - -// Sending functions. - -static int -s_sendmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_) -{ - int sz = (int) zmq_msg_size (msg_); - int rc = s_->send ((zmq::msg_t*) msg_, flags_); - if (unlikely (rc < 0)) - return -1; - return sz; -} - -/* To be deprecated once zmq_msg_send() is stable */ -int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_) -{ - return zmq_msg_send (msg_, s_, flags_); -} - -int zmq_send (void *s_, const void *buf_, size_t len_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq_msg_t msg; - int rc = zmq_msg_init_size (&msg, len_); - if (rc != 0) - return -1; - memcpy (zmq_msg_data (&msg), buf_, len_); - - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - rc = s_sendmsg (s, &msg, flags_); - if (unlikely (rc < 0)) { - int err = errno; - int rc2 = zmq_msg_close (&msg); - errno_assert (rc2 == 0); - errno = err; - return -1; - } - - // Note the optimisation here. We don't close the msg object as it is - // empty anyway. This may change when implementation of zmq_msg_t changes. - return rc; -} - -int zmq_send_const (void *s_, const void *buf_, size_t len_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq_msg_t msg; - int rc = zmq_msg_init_data (&msg, (void*)buf_, len_, NULL, NULL); - if (rc != 0) - return -1; - - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - rc = s_sendmsg (s, &msg, flags_); - if (unlikely (rc < 0)) { - int err = errno; - int rc2 = zmq_msg_close (&msg); - errno_assert (rc2 == 0); - errno = err; - return -1; - } - - // Note the optimisation here. We don't close the msg object as it is - // empty anyway. This may change when implementation of zmq_msg_t changes. - return rc; -} - - -// Send multiple messages. -// TODO: this function has no man page -// -// If flag bit ZMQ_SNDMORE is set the vector is treated as -// a single multi-part message, i.e. the last message has -// ZMQ_SNDMORE bit switched off. -// -int zmq_sendiov (void *s_, iovec *a_, size_t count_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - int rc = 0; - zmq_msg_t msg; - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - - for (size_t i = 0; i < count_; ++i) { - rc = zmq_msg_init_size (&msg, a_[i].iov_len); - if (rc != 0) { - rc = -1; - break; - } - memcpy (zmq_msg_data (&msg), a_[i].iov_base, a_[i].iov_len); - if (i == count_ - 1) - flags_ = flags_ & ~ZMQ_SNDMORE; - rc = s_sendmsg (s, &msg, flags_); - if (unlikely (rc < 0)) { - int err = errno; - int rc2 = zmq_msg_close (&msg); - errno_assert (rc2 == 0); - errno = err; - rc = -1; - break; - } - } - return rc; -} - -// Receiving functions. - -static int -s_recvmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_) -{ - int rc = s_->recv ((zmq::msg_t*) msg_, flags_); - if (unlikely (rc < 0)) - return -1; - return (int) zmq_msg_size (msg_); -} - -/* To be deprecated once zmq_msg_recv() is stable */ -int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_) -{ - return zmq_msg_recv (msg_, s_, flags_); -} - - -int zmq_recv (void *s_, void *buf_, size_t len_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq_msg_t msg; - int rc = zmq_msg_init (&msg); - errno_assert (rc == 0); - - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int nbytes = s_recvmsg (s, &msg, flags_); - if (unlikely (nbytes < 0)) { - int err = errno; - rc = zmq_msg_close (&msg); - errno_assert (rc == 0); - errno = err; - return -1; - } - - // At the moment an oversized message is silently truncated. - // TODO: Build in a notification mechanism to report the overflows. - size_t to_copy = size_t (nbytes) < len_ ? size_t (nbytes) : len_; - memcpy (buf_, zmq_msg_data (&msg), to_copy); - - rc = zmq_msg_close (&msg); - errno_assert (rc == 0); - - return nbytes; -} - -// Receive a multi-part message -// -// Receives up to *count_ parts of a multi-part message. -// Sets *count_ to the actual number of parts read. -// ZMQ_RCVMORE is set to indicate if a complete multi-part message was read. -// Returns number of message parts read, or -1 on error. -// -// Note: even if -1 is returned, some parts of the message -// may have been read. Therefore the client must consult -// *count_ to retrieve message parts successfully read, -// even if -1 is returned. -// -// The iov_base* buffers of each iovec *a_ filled in by this -// function may be freed using free(). -// TODO: this function has no man page -// -int zmq_recviov (void *s_, iovec *a_, size_t *count_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - - size_t count = *count_; - int nread = 0; - bool recvmore = true; - - *count_ = 0; - - for (size_t i = 0; recvmore && i < count; ++i) { - - zmq_msg_t msg; - int rc = zmq_msg_init (&msg); - errno_assert (rc == 0); - - int nbytes = s_recvmsg (s, &msg, flags_); - if (unlikely (nbytes < 0)) { - int err = errno; - rc = zmq_msg_close (&msg); - errno_assert (rc == 0); - errno = err; - nread = -1; - break; - } - - a_[i].iov_len = zmq_msg_size (&msg); - a_[i].iov_base = malloc(a_[i].iov_len); - if (unlikely (!a_[i].iov_base)) { - errno = ENOMEM; - return -1; - } - memcpy(a_[i].iov_base,static_cast<char *> (zmq_msg_data (&msg)), - a_[i].iov_len); - // Assume zmq_socket ZMQ_RVCMORE is properly set. - recvmore = ((zmq::msg_t*) (void *) &msg)->flags () & zmq::msg_t::more; - rc = zmq_msg_close(&msg); - errno_assert (rc == 0); - ++*count_; - ++nread; - } - return nread; -} - -// Message manipulators. - -int zmq_msg_init (zmq_msg_t *msg_) -{ - return ((zmq::msg_t*) msg_)->init (); -} - -int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_) -{ - return ((zmq::msg_t*) msg_)->init_size (size_); -} - -int zmq_msg_init_data (zmq_msg_t *msg_, void *data_, size_t size_, - zmq_free_fn *ffn_, void *hint_) -{ - return ((zmq::msg_t*) msg_)->init_data (data_, size_, ffn_, hint_); -} - -int zmq_msg_send (zmq_msg_t *msg_, void *s_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s_sendmsg (s, msg_, flags_); - return result; -} - -int zmq_msg_recv (zmq_msg_t *msg_, void *s_, int flags_) -{ - if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { - errno = ENOTSOCK; - return -1; - } - zmq::socket_base_t *s = (zmq::socket_base_t *) s_; - int result = s_recvmsg (s, msg_, flags_); - return result; -} - -int zmq_msg_close (zmq_msg_t *msg_) -{ - return ((zmq::msg_t*) msg_)->close (); -} - -int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_) -{ - return ((zmq::msg_t*) dest_)->move (*(zmq::msg_t*) src_); -} - -int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_) -{ - return ((zmq::msg_t*) dest_)->copy (*(zmq::msg_t*) src_); -} - -void *zmq_msg_data (zmq_msg_t *msg_) -{ - return ((zmq::msg_t*) msg_)->data (); -} - -size_t zmq_msg_size (zmq_msg_t *msg_) -{ - return ((zmq::msg_t*) msg_)->size (); -} - -int zmq_msg_more (zmq_msg_t *msg_) -{ - return zmq_msg_get (msg_, ZMQ_MORE); -} - -int zmq_msg_get (zmq_msg_t *msg_, int option_) -{ - switch (option_) { - case ZMQ_MORE: - return (((zmq::msg_t*) msg_)->flags () & zmq::msg_t::more)? 1: 0; - default: - errno = EINVAL; - return -1; - } -} - -int zmq_msg_set (zmq_msg_t *, int, int) -{ - // No options supported at present - errno = EINVAL; - return -1; -} - -// Polling. - -int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) -{ -#if defined ZMQ_POLL_BASED_ON_POLL - if (unlikely (nitems_ < 0)) { - errno = EINVAL; - return -1; - } - if (unlikely (nitems_ == 0)) { - if (timeout_ == 0) - return 0; -#if defined ZMQ_HAVE_WINDOWS - Sleep (timeout_ > 0 ? timeout_ : INFINITE); - return 0; -#elif defined ZMQ_HAVE_ANDROID - usleep (timeout_ * 1000); - return 0; -#else - return usleep (timeout_ * 1000); -#endif - } - - if (!items_) { - errno = EFAULT; - return -1; - } - - zmq::clock_t clock; - uint64_t now = 0; - uint64_t end = 0; - pollfd spollfds[ZMQ_POLLITEMS_DFLT]; - pollfd *pollfds = spollfds; - - if (nitems_ > ZMQ_POLLITEMS_DFLT) { - pollfds = (pollfd*) malloc (nitems_ * sizeof (pollfd)); - alloc_assert (pollfds); - } - - // Build pollset for poll () system call. - for (int i = 0; i != nitems_; i++) { - - // If the poll item is a 0MQ socket, we poll on the file descriptor - // retrieved by the ZMQ_FD socket option. - if (items_ [i].socket) { - size_t zmq_fd_size = sizeof (zmq::fd_t); - if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &pollfds [i].fd, - &zmq_fd_size) == -1) { - if (pollfds != spollfds) - free (pollfds); - return -1; - } - pollfds [i].events = items_ [i].events ? POLLIN : 0; - } - // Else, the poll item is a raw file descriptor. Just convert the - // events to normal POLLIN/POLLOUT for poll (). - else { - pollfds [i].fd = items_ [i].fd; - pollfds [i].events = - (items_ [i].events & ZMQ_POLLIN ? POLLIN : 0) | - (items_ [i].events & ZMQ_POLLOUT ? POLLOUT : 0); - } - } - - bool first_pass = true; - int nevents = 0; - - while (true) { - // Compute the timeout for the subsequent poll. - int timeout; - if (first_pass) - timeout = 0; - else - if (timeout_ < 0) - timeout = -1; - else - timeout = end - now; - - // Wait for events. - while (true) { - int rc = poll (pollfds, nitems_, timeout); - if (rc == -1 && errno == EINTR) { - if (pollfds != spollfds) - free (pollfds); - return -1; - } - errno_assert (rc >= 0); - break; - } - // Check for the events. - for (int i = 0; i != nitems_; i++) { - - items_ [i].revents = 0; - - // The poll item is a 0MQ socket. Retrieve pending events - // using the ZMQ_EVENTS socket option. - if (items_ [i].socket) { - size_t zmq_events_size = sizeof (uint32_t); - uint32_t zmq_events; - if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events, - &zmq_events_size) == -1) { - if (pollfds != spollfds) - free (pollfds); - return -1; - } - if ((items_ [i].events & ZMQ_POLLOUT) && - (zmq_events & ZMQ_POLLOUT)) - items_ [i].revents |= ZMQ_POLLOUT; - if ((items_ [i].events & ZMQ_POLLIN) && - (zmq_events & ZMQ_POLLIN)) - items_ [i].revents |= ZMQ_POLLIN; - } - // Else, the poll item is a raw file descriptor, simply convert - // the events to zmq_pollitem_t-style format. - else { - if (pollfds [i].revents & POLLIN) - items_ [i].revents |= ZMQ_POLLIN; - if (pollfds [i].revents & POLLOUT) - items_ [i].revents |= ZMQ_POLLOUT; - if (pollfds [i].revents & ~(POLLIN | POLLOUT)) - items_ [i].revents |= ZMQ_POLLERR; - } - - if (items_ [i].revents) - nevents++; - } - - // If timout is zero, exit immediately whether there are events or not. - if (timeout_ == 0) - break; - - // If there are events to return, we can exit immediately. - if (nevents) - break; - - // At this point we are meant to wait for events but there are none. - // If timeout is infinite we can just loop until we get some events. - if (timeout_ < 0) { - if (first_pass) - first_pass = false; - continue; - } - - // The timeout is finite and there are no events. In the first pass - // we get a timestamp of when the polling have begun. (We assume that - // first pass have taken negligible time). We also compute the time - // when the polling should time out. - if (first_pass) { - now = clock.now_ms (); - end = now + timeout_; - if (now == end) - break; - first_pass = false; - continue; - } - - // Find out whether timeout have expired. - now = clock.now_ms (); - if (now >= end) - break; - } - - if (pollfds != spollfds) - free (pollfds); - return nevents; - -#elif defined ZMQ_POLL_BASED_ON_SELECT - - if (unlikely (nitems_ < 0)) { - errno = EINVAL; - return -1; - } - if (unlikely (nitems_ == 0)) { - if (timeout_ == 0) - return 0; -#if defined ZMQ_HAVE_WINDOWS - Sleep (timeout_ > 0 ? timeout_ : INFINITE); - return 0; -#else - return usleep (timeout_ * 1000); -#endif - } - zmq::clock_t clock; - uint64_t now = 0; - uint64_t end = 0; - - // Ensure we do not attempt to select () on more than FD_SETSIZE - // file descriptors. - zmq_assert (nitems_ <= FD_SETSIZE); - - fd_set pollset_in; - FD_ZERO (&pollset_in); - fd_set pollset_out; - FD_ZERO (&pollset_out); - fd_set pollset_err; - FD_ZERO (&pollset_err); - - zmq::fd_t maxfd = 0; - - // Build the fd_sets for passing to select (). - for (int i = 0; i != nitems_; i++) { - - // If the poll item is a 0MQ socket we are interested in input on the - // notification file descriptor retrieved by the ZMQ_FD socket option. - if (items_ [i].socket) { - size_t zmq_fd_size = sizeof (zmq::fd_t); - zmq::fd_t notify_fd; - if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, ¬ify_fd, - &zmq_fd_size) == -1) - return -1; - if (items_ [i].events) { - FD_SET (notify_fd, &pollset_in); - if (maxfd < notify_fd) - maxfd = notify_fd; - } - } - // Else, the poll item is a raw file descriptor. Convert the poll item - // events to the appropriate fd_sets. - else { - if (items_ [i].events & ZMQ_POLLIN) - FD_SET (items_ [i].fd, &pollset_in); - if (items_ [i].events & ZMQ_POLLOUT) - FD_SET (items_ [i].fd, &pollset_out); - if (items_ [i].events & ZMQ_POLLERR) - FD_SET (items_ [i].fd, &pollset_err); - if (maxfd < items_ [i].fd) - maxfd = items_ [i].fd; - } - } - - bool first_pass = true; - int nevents = 0; - fd_set inset, outset, errset; - - while (true) { - - // Compute the timeout for the subsequent poll. - timeval timeout; - timeval *ptimeout; - if (first_pass) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - ptimeout = &timeout; - } - else - if (timeout_ < 0) - ptimeout = NULL; - else { - timeout.tv_sec = (long) ((end - now) / 1000); - timeout.tv_usec = (long) ((end - now) % 1000 * 1000); - ptimeout = &timeout; - } - - // Wait for events. Ignore interrupts if there's infinite timeout. - while (true) { - memcpy (&inset, &pollset_in, sizeof (fd_set)); - memcpy (&outset, &pollset_out, sizeof (fd_set)); - memcpy (&errset, &pollset_err, sizeof (fd_set)); -#if defined ZMQ_HAVE_WINDOWS - int rc = select (0, &inset, &outset, &errset, ptimeout); - if (unlikely (rc == SOCKET_ERROR)) { - errno = zmq::wsa_error_to_errno (WSAGetLastError ()); - wsa_assert (errno == ENOTSOCK); - return -1; - } -#else - int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout); - if (unlikely (rc == -1)) { - errno_assert (errno == EINTR || errno == EBADF); - return -1; - } -#endif - break; - } - - // Check for the events. - for (int i = 0; i != nitems_; i++) { - - items_ [i].revents = 0; - - // The poll item is a 0MQ socket. Retrieve pending events - // using the ZMQ_EVENTS socket option. - if (items_ [i].socket) { - size_t zmq_events_size = sizeof (uint32_t); - uint32_t zmq_events; - if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events, - &zmq_events_size) == -1) - return -1; - if ((items_ [i].events & ZMQ_POLLOUT) && - (zmq_events & ZMQ_POLLOUT)) - items_ [i].revents |= ZMQ_POLLOUT; - if ((items_ [i].events & ZMQ_POLLIN) && - (zmq_events & ZMQ_POLLIN)) - items_ [i].revents |= ZMQ_POLLIN; - } - // Else, the poll item is a raw file descriptor, simply convert - // the events to zmq_pollitem_t-style format. - else { - if (FD_ISSET (items_ [i].fd, &inset)) - items_ [i].revents |= ZMQ_POLLIN; - if (FD_ISSET (items_ [i].fd, &outset)) - items_ [i].revents |= ZMQ_POLLOUT; - if (FD_ISSET (items_ [i].fd, &errset)) - items_ [i].revents |= ZMQ_POLLERR; - } - - if (items_ [i].revents) - nevents++; - } - - // If timout is zero, exit immediately whether there are events or not. - if (timeout_ == 0) - break; - - // If there are events to return, we can exit immediately. - if (nevents) - break; - - // At this point we are meant to wait for events but there are none. - // If timeout is infinite we can just loop until we get some events. - if (timeout_ < 0) { - if (first_pass) - first_pass = false; - continue; - } - - // The timeout is finite and there are no events. In the first pass - // we get a timestamp of when the polling have begun. (We assume that - // first pass have taken negligible time). We also compute the time - // when the polling should time out. - if (first_pass) { - now = clock.now_ms (); - end = now + timeout_; - if (now == end) - break; - first_pass = false; - continue; - } - - // Find out whether timeout have expired. - now = clock.now_ms (); - if (now >= end) - break; - } - - return nevents; - -#else - // Exotic platforms that support neither poll() nor select(). - errno = ENOTSUP; - return -1; -#endif -} - -#if defined ZMQ_POLL_BASED_ON_SELECT -#undef ZMQ_POLL_BASED_ON_SELECT -#endif -#if defined ZMQ_POLL_BASED_ON_POLL -#undef ZMQ_POLL_BASED_ON_POLL -#endif - -// The proxy functionality - -int zmq_proxy (void *frontend_, void *backend_, void *control_) -{ - if (!frontend_ || !backend_) { - errno = EFAULT; - return -1; - } - return zmq::proxy ( - (zmq::socket_base_t*) frontend_, - (zmq::socket_base_t*) backend_, - (zmq::socket_base_t*) control_); -} - -// The deprecated device functionality - -int zmq_device (int /* type */, void *frontend_, void *backend_) -{ - return zmq::proxy ( - (zmq::socket_base_t*) frontend_, - (zmq::socket_base_t*) backend_, NULL); -} diff --git a/src/zmq_utils.cpp b/src/zmq_utils.cpp deleted file mode 100644 index 148ef95..0000000 --- a/src/zmq_utils.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file - - This file is part of 0MQ. - - 0MQ is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - 0MQ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "platform.hpp" - -#include "clock.hpp" -#include "err.hpp" -#include "thread.hpp" -#include <assert.h> -#include "../include/zmq_utils.h" - -#if !defined ZMQ_HAVE_WINDOWS -#include <unistd.h> -#else -#include "windows.hpp" -#endif -#ifdef HAVE_LIBSODIUM -# include <sodium.h> -#endif - - -void zmq_sleep (int seconds_) -{ -#if defined ZMQ_HAVE_WINDOWS - Sleep (seconds_ * 1000); -#else - sleep (seconds_); -#endif -} - -void *zmq_stopwatch_start () -{ - uint64_t *watch = (uint64_t*) malloc (sizeof (uint64_t)); - alloc_assert (watch); - *watch = zmq::clock_t::now_us (); - return (void*) watch; -} - -unsigned long zmq_stopwatch_stop (void *watch_) -{ - uint64_t end = zmq::clock_t::now_us (); - uint64_t start = *(uint64_t*) watch_; - free (watch_); - return (unsigned long) (end - start); -} - -void *zmq_threadstart(zmq_thread_fn* func, void* arg) -{ - zmq::thread_t* thread = new zmq::thread_t; - thread->start(func, arg); - return thread; -} - -void zmq_threadclose(void* thread) -{ - zmq::thread_t* pThread = static_cast<zmq::thread_t*>(thread); - pThread->stop(); - delete pThread; -} - -// Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding - -// Maps base 256 to base 85 -static char encoder [85 + 1] = { - "0123456789" "abcdefghij" "klmnopqrst" "uvwxyzABCD" - "EFGHIJKLMN" "OPQRSTUVWX" "YZ.-:+=^!/" "*?&<>()[]{" - "}@%$#" -}; - -// Maps base 85 to base 256 -// We chop off lower 32 and higher 128 ranges -static uint8_t decoder [96] = { - 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00, - 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47, - 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, - 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, - 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00, - 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 -}; - -// -------------------------------------------------------------------------- -// Encode a binary frame as a string; destination string MUST be at least -// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns -// dest. Size must be a multiple of 4. -// Returns NULL and sets errno = EINVAL for invalid input. - -char *zmq_z85_encode (char *dest, uint8_t *data, size_t size) -{ - if (size % 4 != 0) { - errno = EINVAL; - return NULL; - } - unsigned int char_nbr = 0; - unsigned int byte_nbr = 0; - uint32_t value = 0; - while (byte_nbr < size) { - // Accumulate value in base 256 (binary) - value = value * 256 + data [byte_nbr++]; - if (byte_nbr % 4 == 0) { - // Output value in base 85 - unsigned int divisor = 85 * 85 * 85 * 85; - while (divisor) { - dest [char_nbr++] = encoder [value / divisor % 85]; - divisor /= 85; - } - value = 0; - } - } - assert (char_nbr == size * 5 / 4); - dest [char_nbr] = 0; - return dest; -} - - -// -------------------------------------------------------------------------- -// Decode an encoded string into a binary frame; dest must be at least -// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string) -// must be a multiple of 5. -// Returns NULL and sets errno = EINVAL for invalid input. - -uint8_t *zmq_z85_decode (uint8_t *dest, char *string) -{ - if (strlen (string) % 5 != 0) { - errno = EINVAL; - return NULL; - } - unsigned int byte_nbr = 0; - unsigned int char_nbr = 0; - unsigned int string_len = strlen (string); - uint32_t value = 0; - while (char_nbr < string_len) { - // Accumulate value in base 85 - value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32]; - if (char_nbr % 5 == 0) { - // Output value in base 256 - unsigned int divisor = 256 * 256 * 256; - while (divisor) { - dest [byte_nbr++] = value / divisor % 256; - divisor /= 256; - } - value = 0; - } - } - assert (byte_nbr == strlen (string) * 4 / 5); - return dest; -} - -// -------------------------------------------------------------------------- -// Generate a public/private keypair with libsodium. -// Generated keys will be 40 byte z85-encoded strings. -// Returns 0 on success, -1 on failure, setting errno. -// Sets errno = ENOTSUP in the absence of libsodium. - -int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) -{ -#ifdef HAVE_LIBSODIUM -# if crypto_box_PUBLICKEYBYTES != 32 \ - || crypto_box_SECRETKEYBYTES != 32 -# error "libsodium not built correctly" -# endif - - uint8_t public_key [32]; - uint8_t secret_key [32]; - - int rc = crypto_box_keypair (public_key, secret_key); - // Is there a sensible errno to set here? - if (rc) - return rc; - - zmq_z85_encode (z85_public_key, public_key, 32); - zmq_z85_encode (z85_secret_key, secret_key, 32); - - return 0; -#else // requires libsodium - errno = ENOTSUP; - return -1; -#endif -} |