Ejemplo n.º 1
0
int main (void)
{
    clonesrv_t *self = (clonesrv_t *) zmalloc (sizeof (clonesrv_t));

    self->port = 5556;
    self->ctx = zctx_new ();
    self->kvmap = zhash_new ();
    self->loop = zloop_new ();
    zloop_set_verbose (self->loop, FALSE);

    //  Set up our clone server sockets
    self->snapshot  = zsocket_new (self->ctx, ZMQ_ROUTER);
    self->publisher = zsocket_new (self->ctx, ZMQ_PUB);
    self->collector = zsocket_new (self->ctx, ZMQ_PULL);
    zsocket_bind (self->snapshot,  "tcp://*:%d", self->port);
    zsocket_bind (self->publisher, "tcp://*:%d", self->port + 1);
    zsocket_bind (self->collector, "tcp://*:%d", self->port + 2);

    //  Register our handlers with reactor
    zmq_pollitem_t poller = { self->snapshot, 0, ZMQ_POLLIN };
    zloop_poller (self->loop, &poller, s_snapshots, self);
    poller.socket = self->collector;
    zloop_poller (self->loop, &poller, s_collector, self);
    zloop_timer  (self->loop, 1000, 0, s_flush_ttl, self);

    //  Run reactor until process interrupted
    zloop_start (self->loop);

    zloop_destroy (&self->loop);
    zhash_destroy (&self->kvmap);
    zctx_destroy (&self->ctx);
    free (self);
    return 0;
}
Ejemplo n.º 2
0
Archivo: evsub.c Proyecto: bartuer/bew
/* url subtitle arguments */
int main (int argc, char *argv []) {
  void *context = zmq_init (1);

  void *subscriber = zmq_socket (context, ZMQ_SUB);
  size_t title_len = 0;
  assert(zmq_connect (subscriber, argv[1]) == 0);
  assert(title_len = strlen(argv[2]) > 1);
  assert(zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, argv[2], title_len) == 0);

  Bool verbose = 0;
  zloop_t *loop = zloop_new ();
  assert (loop);
  zloop_set_verbose (loop, verbose);

  zmq_pollitem_t sub_event = { subscriber, 0, ZMQ_POLLIN };
  if ( argc > 3 ) {
    assert(zloop_poller (loop, &sub_event, subscriber_cb, (void*)(argv + 3)) == 0);    
  } else {
    assert(zloop_poller (loop, &sub_event, subscriber_cb, NULL) == 0);    
  }

  zloop_start (loop);

  zloop_destroy (&loop);
  assert (loop == NULL);
  zmq_close (subscriber);
  zmq_term (context);

  return 0;
}
int main (int argc, char** argv)
{
    int port = 5556;

#ifdef FF_USE_LIBGC
    GC_INIT();
    set_program_name (argv[0]);
#endif

    if( argc >= 2 )
	port = atoi( argv[1] );
	
    clonesrv_t *self = (clonesrv_t *) zmalloc (sizeof (clonesrv_t));
    self->port = port;
    self->ctx = zctx_new ();
    self->kvmap = zhash_new ();
    self->loop = zloop_new ();
    zloop_set_verbose (self->loop, false);

    //  Set up our clone server sockets
    self->snapshot  = zsocket_new (self->ctx, ZMQ_ROUTER);
    zsocket_bind (self->snapshot,  "tcp://*:%d", self->port + socket_srv_offset_snapshot );
    self->publisher = zsocket_new (self->ctx, ZMQ_PUB);
    zsocket_bind (self->publisher, "tcp://*:%d", self->port + socket_srv_offset_publisher );
    self->collector = zsocket_new (self->ctx, ZMQ_PULL);
    zsocket_bind (self->collector, "tcp://*:%d", self->port + socket_srv_offset_collector );
    self->ping = zsocket_new (self->ctx, ZMQ_REP);
    zsocket_bind (self->ping,      "tcp://*:%d", self->port + socket_srv_offset_ping );

    //  Register our handlers with reactor
    zmq_pollitem_t poller = { 0, 0, ZMQ_POLLIN };
    poller.socket = self->snapshot;
    zloop_poller (self->loop, &poller, s_snapshots, self);
    poller.socket = self->collector;
    zloop_poller (self->loop, &poller, s_collector, self);
    zloop_timer (self->loop, 1000, 0, s_flush_ttl, self);
    poller.socket = self->ping;
    zloop_poller (self->loop, &poller, s_ping, self);

    
    
    DEBUG ("I: server up and running on port:%d...", port );
    //  Run reactor until process interrupted
    zloop_start (self->loop);

    zloop_destroy (&self->loop);
    zhash_destroy (&self->kvmap);
    zctx_destroy (&self->ctx);
    free (self);
    return 0;
}
Ejemplo n.º 4
0
bstar_t *
bstar_new (int primary, char *local, char *remote)
{
    bstar_t
        *self;

    self = (bstar_t *) zmalloc (sizeof (bstar_t));

    //  Initialize the Binary Star
    self->ctx = zctx_new ();
    self->loop = zloop_new ();
    self->state = primary? STATE_PRIMARY: STATE_BACKUP;

    //  Create publisher for state going to peer
    self->statepub = zsocket_new (self->ctx, ZMQ_PUB);
    zsocket_bind (self->statepub, local);

    //  Create subscriber for state coming from peer
    self->statesub = zsocket_new (self->ctx, ZMQ_SUB);
    zsocket_set_subscribe (self->statesub, "");
    zsocket_connect (self->statesub, remote);

    //  Set-up basic reactor events
    zloop_timer (self->loop, BSTAR_HEARTBEAT, 0, s_send_state, self);
    zmq_pollitem_t poller = { self->statesub, 0, ZMQ_POLLIN };
    zloop_poller (self->loop, &poller, s_recv_state, self);
    return self;
}
Ejemplo n.º 5
0
Archivo: vtx_tcp.c Proyecto: imatix/vtx
static void
peering_raise (peering_t *self)
{
    vocket_t *vocket = self->vocket;
    driver_t *driver = self->driver;
    if (driver->verbose)
        zclock_log ("I: (tcp) bring up peering to %s", self->address);

    if (!self->alive) {
        self->alive = TRUE;
        zlist_append (vocket->live_peerings, self);

        //  Send ZMTP handshake, which is an empty message
        zmq_msg_t msg;
        zmq_msg_init_size (&msg, 0);
        s_queue_output (self, &msg, FALSE);

        //  If we can now route to peerings, start reading from msgpipe
        if (zlist_size (vocket->live_peerings) == vocket->min_peerings) {
            //  Ask reactor to start monitoring vocket's msgpipe pipe
            zmq_pollitem_t item = { vocket->msgpipe, 0, ZMQ_POLLIN, 0 };
            zloop_poller (driver->loop, &item, s_vocket_input, vocket);
        }
    }
}
Ejemplo n.º 6
0
// Handle input from worker, on backend
int s_handle_backend(zloop_t *loop, zmq_pollitem_t *poller, void *arg)
{
	// Use worker identity for load-balancing
	lbbroker_t *self = (lbbroker_t *)arg;
	zmsg_t *msg = zmsg_recv(self->backend);
	if (msg) {
		zframe_t *identity = zmsg_unwrap(msg);
		zlist_append(self->workers, identity);

		// Enable reader on frontend if we went from 0 to 1 workers
		if (zlist_size(self->workers) == 1) {
			zmq_pollitem_t poller = { self->frontend, 0, ZMQ_POLLIN };
			zloop_poller(loop, &poller, s_handle_frontend, self);
		}

		// Forward message to client if it's not a READY
		zframe_t *frame = zmsg_first(msg);
		if (memcmp(zframe_data(frame), WORKER_READY, strlen(WORKER_READY)) == 0) {
			zmsg_destroy(&msg);
		} else {
			zmsg_send(&msg, self->frontend);
		}
	}
	return 0;
}
Ejemplo n.º 7
0
int 
bstar_voter(bstar_t *self, char *endpoint, int type, zloop_fn handler, void *arg)
{
	void *socket = zsocket_new(self->ctx, type);
	zsocket_bind(socket, endpoint);
	assert(!self->voter_fn);
	self->voter_fn = handler;
	self->voter_arg = arg;
	zmq_pollitem_t poller = {socket, 0, ZMQ_POLLIN};
	return zloop_poller(self->loop, &poller, s_voter_ready, self);
}
Ejemplo n.º 8
0
int main(int argc, char const * const *argv)
{
  int rc;

  zsys_set_sndhwm(1);
  zsys_set_linger(100);

  void *pusher = zsock_new(ZMQ_PUSH);
  assert(pusher);
  zsock_set_sndhwm(pusher, 1000);
  zsock_set_linger(pusher, 500);
  rc = zsock_connect(pusher, "tcp://localhost:12345");
  assert(rc==0);

  void *puller = zsock_new(ZMQ_PULL);
  assert(puller);
  zsock_set_rcvhwm(puller, 1000);
  zsock_set_linger(puller, 500);
  rc = zsock_bind(puller, "tcp://*:12345");
  if (rc != 12345){
    printf("bind failed: %s\n", zmq_strerror(errno));
  }
  assert(rc == 12345);

  void *publisher = zsock_new(ZMQ_PUB);
  assert(publisher);
  zsock_set_sndhwm(publisher, 1000);
  zsock_set_linger(publisher, 500);
  rc = zsock_bind(publisher, "tcp://*:12346");
  assert(rc==12346);

  // set up event loop
  zloop_t *loop = zloop_new();
  assert(loop);
  zloop_set_verbose(loop, 0);

  // push data every 10 ms
  rc = zloop_timer(loop, 1, 0, timer_event, pusher);
  assert(rc != -1);

  zmq_pollitem_t item;
  item.socket = puller;
  item.events = ZMQ_POLLIN;
  rc = zloop_poller(loop, &item, forward, publisher);
  assert(rc == 0);

  rc = zloop_start(loop);
  printf("zloop return: %d", rc);

  zloop_destroy(&loop);
  assert(loop == NULL);

  return 0;
}
Ejemplo n.º 9
0
Archivo: vtx_tcp.c Proyecto: imatix/vtx
static void
peering_poller (peering_t *self, int events)
{
    driver_t *driver = self->driver;
    if (self->events != events) {
        zmq_pollitem_t item = { NULL, self->handle, events, 0 };
        zloop_poller_end (driver->loop, &item);
        if (events)
            zloop_poller (driver->loop, &item, s_peering_activity, self);
        self->events = events;
    }
}
Ejemplo n.º 10
0
static int
s_new_slave (zloop_t *loop, zmq_pollitem_t *unused, void *args)
{
    clonesrv_t *self = (clonesrv_t *) args;

    zhash_destroy (&self->kvmap);
    self->master = FALSE;
    self->slave = TRUE;
    zmq_pollitem_t poller = { self->subscriber, 0, ZMQ_POLLIN };
    zloop_poller (bstar_zloop (self->bstar), &poller, s_subscriber, self);

    return 0;
}
Ejemplo n.º 11
0
Archivo: vtx_tcp.c Proyecto: imatix/vtx
static vocket_t *
vocket_new (driver_t *driver, int socktype, char *vtxname)
{
    assert (driver);
    vocket_t *self = (vocket_t *) zmalloc (sizeof (vocket_t));

    self->driver = driver;
    self->vtxname = strdup (vtxname);
    self->binding_hash = zhash_new ();
    self->peering_hash = zhash_new ();
    self->peering_list = zlist_new ();
    self->live_peerings = zlist_new ();
    self->socktype = socktype;

    uint index;
    for (index = 0; index < tblsize (s_vocket_config); index++)
        if (socktype == s_vocket_config [index].socktype)
            break;

    if (index < tblsize (s_vocket_config)) {
        self->routing = s_vocket_config [index].routing;
        self->nomnom = s_vocket_config [index].nomnom;
        self->min_peerings = s_vocket_config [index].min_peerings;
        self->max_peerings = s_vocket_config [index].max_peerings;
    }
    else {
        zclock_log ("E: invalid vocket type %d", socktype);
        exit (1);
    }
    //  Create msgpipe vocket and connect over inproc to vtxname
    self->msgpipe = zsocket_new (driver->ctx, ZMQ_PAIR);
    assert (self->msgpipe);
    zsocket_connect (self->msgpipe, "inproc://%s", vtxname);

    //  If we drop on no peerings, start routing input now
    if (self->min_peerings == 0) {
        //  Ask reactor to start monitoring vocket's msgpipe pipe
        zmq_pollitem_t item = { self->msgpipe, 0, ZMQ_POLLIN, 0 };
        zloop_poller (driver->loop, &item, s_vocket_input, self);
    }
    //  Store this vocket per driver so that driver can cleanly destroy
    //  all its vockets when it is destroyed.
    zlist_push (driver->vockets, self);

    //* Start transport-specific work
    self->inbuf_max = VTX_TCP_INBUF_MAX;
    self->outbuf_max = VTX_TCP_OUTBUF_MAX;
    //* End transport-specific work

    return self;
}
Ejemplo n.º 12
0
maltcp_ctx_connection_t *maltcp_ctx_socket_connect(maltcp_ctx_t *self, mal_uri_t *socket_uri) {
  maltcp_ctx_connection_t *cnx_ptr = (maltcp_ctx_connection_t *) zhash_lookup(self->cnx_table, socket_uri);

  if (cnx_ptr == NULL) {
    clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: open a new PTP socket\n");

    // Create a new connection
    struct hostent *server;
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket == -1) {
      clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to create client socket: %s\n", strerror(errno));
      return NULL;
    }

    char *ipaddr = maltcp_get_host_from_uri(socket_uri);
    int port = maltcp_get_port_from_uri(socket_uri);
    clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: %s %d\n", ipaddr, port);
    if ((server = gethostbyname(ipaddr)) == NULL) {
      clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to to get address: %s\n", strerror(errno));
      free(ipaddr);
      return NULL;
    }
    free(ipaddr);

    struct sockaddr_in server_addr;
    bzero((char *) &server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, (char *)&server_addr.sin_addr.s_addr, server->h_length);
    server_addr.sin_port = htons(port);

    if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
      clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to connect: %s\n", strerror(errno));
      return NULL;
    }
    clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: connected to %s\n", socket_uri);

    clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: update TCP connections table\n");
    cnx_ptr = maltcp_ctx_connection_register_outgoing(self, client_socket, socket_uri);

    // Register a zloop poller for this connection.
    zmq_pollitem_t poller = { NULL, client_socket, ZMQ_POLLIN };
    int rc = zloop_poller(self->zloop, &poller, maltcp_ctx_socket_receive, self);
    assert(rc == 0);
  } else {
    clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: use existing connection (%d) for %s\n", cnx_ptr->socket, socket_uri);
  }

  return cnx_ptr;
}
Ejemplo n.º 13
0
Archivo: vtx_tcp.c Proyecto: imatix/vtx
static driver_t *
driver_new (zctx_t *ctx, void *pipe)
{
    driver_t *self = (driver_t *) zmalloc (sizeof (driver_t));
    self->ctx = ctx;
    self->pipe = pipe;
    self->vockets = zlist_new ();
    self->loop = zloop_new ();
    self->scheme = VTX_TCP_SCHEME;

    //  Reactor starts by monitoring the driver control pipe
    zmq_pollitem_t item = { self->pipe, 0, ZMQ_POLLIN };
    zloop_poller (self->loop, &item, s_driver_control, self);
    return self;
}
Ejemplo n.º 14
0
static int
s_new_passive (zloop_t *loop, zmq_pollitem_t *unused, void *args)
{
    clonesrv_t *self = (clonesrv_t *) args;

    zhash_destroy (&self->kvmap);
    self->active = false;
    self->passive = true;

    //  Start subscribing to updates
    zmq_pollitem_t poller = { self->subscriber, 0, ZMQ_POLLIN };
    zloop_poller (bstar_zloop (self->bstar), &poller, s_subscriber, self);

    return 0;
}
Ejemplo n.º 15
0
// This function is called when an incoming connection is detected on the
// listening socket. It accepts the connection and registers the appropriate
// poller to receive message.
int maltcp_ctx_socket_accept(zloop_t *zloop, zmq_pollitem_t *poller, void *arg) {
  maltcp_ctx_t *self = (maltcp_ctx_t *) arg;

  clog_debug(maltcp_logger, "maltcp_ctx: TCP server socket accept.\n");
  if (self->mal_socket == -1) {
    // The context is closed, return
    clog_debug(maltcp_logger, "maltcp_ctx_socket_accept: socket (%d) closed\n", poller->fd);
    return -1;
  }

  // Accept incoming connection and register it.
  struct sockaddr src_addr;
  int new_socket = -1;
  socklen_t len = sizeof(struct sockaddr_in);

  // Note: May be we could use poller->fd to replace self->mal_socket
  if ((new_socket = accept(self->mal_socket, &src_addr, &len)) == -1) {
    clog_error(maltcp_logger, "Failed to accept: %s\n", strerror(errno));
    return -1;
  }

  if (clog_is_loggable(maltcp_logger, CLOG_DEBUG_LEVEL)) {
    // Needed only for debug.
    char src_ipstr[INET6_ADDRSTRLEN];
    int src_port;

    if (src_addr.sa_family == AF_INET) {
      struct sockaddr_in *s = (struct sockaddr_in *)&src_addr;
      src_port = ntohs(s->sin_port);
      inet_ntop(AF_INET, &s->sin_addr, src_ipstr, sizeof src_ipstr);
    } else { // AF_INET6
      struct sockaddr_in6 *s = (struct sockaddr_in6 *)&src_addr;
      src_port = ntohs(s->sin6_port);
      inet_ntop(AF_INET6, &s->sin6_addr, src_ipstr, sizeof src_ipstr);
    }
    clog_debug(maltcp_logger, "maltcp_ctx_socket_accept: Source URI: %s%s:%d\n", MALTCP_URI, src_ipstr, src_port);
  }

  zmq_pollitem_t poller2 = { NULL, new_socket, ZMQ_POLLIN };
  int rc = zloop_poller(zloop, &poller2, maltcp_ctx_socket_receive, self);
  assert(rc == 0);

  // Note: do not register the connection since the uri is not yet precisely known.

  clog_debug(maltcp_logger, "maltcp_ctx: TCP connection established.\n");

  return 0;
}
Ejemplo n.º 16
0
void rabbitmq_listener(zsock_t *pipe, void* args)
{
    set_thread_name("rabbit-consumer");

    // signal readyiness immediately so that zmq publishers are already processed
    // while the rabbitmq exchanges/queues/bindings are created
    zsock_signal(pipe, 0);

    amqp_connection_state_t conn = setup_amqp_connection();
    int last_channel = rabbitmq_setup_queues(conn, (zlist_t*)args);

    // connect to the receiver socket
    zsock_t *receiver = zsock_new(ZMQ_PUSH);
    zsock_set_sndhwm(receiver, 10000);
    zsock_connect(receiver, "inproc://receiver");

    // set up event loop
    zloop_t *loop = zloop_new();
    assert(loop);
    zloop_set_verbose(loop, 0);
    zloop_ignore_interrupts(loop);

    // register actor command handler
    int rc = zloop_reader(loop, pipe, pipe_command, NULL);
    assert(rc==0);

    // register rabbitmq socket for pollin events
    zmq_pollitem_t rabbit_item = {
        .fd = amqp_get_sockfd(conn),
        .events = ZMQ_POLLIN
    };
    rabbit_listener_state_t listener_state = {
        .conn = conn,
        .receiver = zsock_resolve(receiver)
    };
    rc = zloop_poller(loop, &rabbit_item, rabbitmq_consume_message_and_forward, &listener_state);
    assert(rc==0);

    // start event loop
    zloop_start(loop);

    // shutdown
    zloop_destroy(&loop);
    zsock_destroy(&receiver);
    shutdown_amqp_connection(conn, 0, last_channel);
}
Ejemplo n.º 17
0
void start_loop(int count)
{
	zloop_t *loop = zloop_new();
	assert(loop);
	
	zmq_pollitem_t poll_socket = { dealer,  0, ZMQ_POLLIN, 0 };
	zloop_poller ( loop, &poll_socket, event, NULL);
	
	zloop_timer(loop, 1000, 0, sleep_loop, &count);
	zloop_timer(loop, 1000, 0, info_loop, &count);
	
	struct timeval tv;
	gettimeofday(&tv,NULL);
	start = (uint64_t)tv.tv_sec;
	
	zloop_start (loop);
	return;
}
Ejemplo n.º 18
0
int main(void)
{
	zctx_t *ctx = zctx_new();
	lbbroker_t *self = (lbbroker_t *)zmalloc(sizeof(lbbroker_t));
	self->frontend = zsocket_new(ctx, ZMQ_ROUTER);
	self->backend = zsocket_new(ctx, ZMQ_ROUTER);

#if (defined (WIN32))
	zsocket_bind(self->frontend, "tcp://*:5672"); // frontend
	zsocket_bind(self->backend, "tcp://*:5673"); // backend
#else
	zsocket_bind(self->frontend, "ipc://frontend.ipc");
	zsocket_bind(self->backend, "ipc://backend.ipc");
#endif

	int client_nbr;
	for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++)
		zthread_new(client_task, NULL);
	int worker_nbr;
	for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++)
		zthread_new(worker_task, NULL);

	// Queue of available workers
	self->workers = zlist_new();

	// Prepare reactor and fire it up
	zloop_t *reactor = zloop_new();
	zmq_pollitem_t poller = { self->backend, 0, ZMQ_POLLIN };
	zloop_poller(reactor, &poller, s_handle_backend, self);
	zloop_start(reactor);
	zloop_destroy(&reactor);

	// When we're done, clean up properly
	while (zlist_size(self->workers)) {
		zframe_t *frame = (zframe_t *)zlist_pop(self->workers);
		zframe_destroy(&frame);
	}
	zlist_destroy(&self->workers);
	zctx_destroy(&ctx);
	free(self);
	return 0;
}
Ejemplo n.º 19
0
Archivo: zloop.c Proyecto: fars/czmq
void
zloop_test (bool verbose)
{
    printf (" * zloop: ");
    int rc = 0;
    //  @selftest
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    void *output = zsocket_new (ctx, ZMQ_PAIR);
    assert (output);
    zsocket_bind (output, "inproc://zloop.test");
    void *input = zsocket_new (ctx, ZMQ_PAIR);
    assert (input);
    zsocket_connect (input, "inproc://zloop.test");

    zloop_t *loop = zloop_new ();
    assert (loop);
    zloop_set_verbose (loop, verbose);

    //  Create a timer that will be canceled
    int timer_id = zloop_timer (loop, 1000, 1, s_timer_event, NULL);
    zloop_timer (loop, 5, 1, s_cancel_timer_event, &timer_id);
    
    //  After 20 msecs, send a ping message to output
    zloop_timer (loop, 20, 1, s_timer_event, output);
    
    //  When we get the ping message, end the reactor
    zmq_pollitem_t poll_input = { input, 0, ZMQ_POLLIN };
    rc = zloop_poller (loop, &poll_input, s_socket_event, NULL);    
    assert (rc == 0);
    zloop_set_tolerant (loop, &poll_input);
    zloop_start (loop);

    zloop_destroy (&loop);
    assert (loop == NULL);

    zctx_destroy (&ctx);
    //  @end
    printf ("OK\n");
}
Ejemplo n.º 20
0
int main (int argc, char *argv [])
{
  if (argc == 2) {
    count = atoi(argv[1]);
  }

  zctx_t *ctx = zctx_new();
  void *client = zsocket_new(ctx, ZMQ_ROUTER);
  zloop_t *loop = zloop_new();

  zsocket_bind(client, "ipc:///tmp/zmqtestbr");

  zmq_pollitem_t items [] = { { client, 0, ZMQ_POLLIN, 0 } };
  zloop_poller(loop, items, recvHandler, client);

  zloop_start(loop);

  zloop_destroy(&loop);
  zctx_destroy(&ctx);
  return 0;
}
Ejemplo n.º 21
0
bstar_t *
bstar_new(int primary, char *local, char *remote)
{
	bstar_t *self;

	self = (bstar_t *)zmalloc(sizeof(bstar_t));

	self->ctx = zctx_new();
	self->loop = zloop_new();
	self->state = primary ? STATE_PRIMARY : STATE_BACKUP;

	self->statepub = zsocket_new(self->ctx, ZMQ_PUB);
	zsocket_bind(self->statepub, local);

	self->statesub = zsocket_new(self->ctx, ZMQ_SUB);
	zsocket_set_subscribe(self->statesub, "");
	zsocket_connect(self->statesub, remote);

	zloop_timer(self->loop, BSTAR_HEARTBEAT, 0, s_send_state, self);
	zmq_pollitem_t poller = {self->statesub, 0, ZMQ_POLLIN};
	zloop_poller(self->loop, &poller, s_recv_state, self);
	return self;
}
Ejemplo n.º 22
0
static void forkzio_pipe_thd (void *args, zctx_t *zctx, void *zs)
{
    forkzio_t ctx = args;
    zmq_pollitem_t zp = { .fd = -1, .socket = zs, .events = ZMQ_POLLIN };
    zloop_t *zloop;
    pid_t pid;

    if (!(zloop = zloop_new ()))
        oom ();

    /* child stdin <= zs
     */
    zloop_poller (zloop, &zp, (zloop_fn *)forkzio_zsock_cb, ctx);
    ctx->zio[0] = zio_pipe_writer_create ("stdin", NULL);
    if (zio_zloop_attach (ctx->zio[0], zloop) < 0)
        err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[0]));

    /* child stdout => zs
     */
    ctx->zio[1] = zio_pipe_reader_create ("stdout", zs, ctx);
    zio_set_close_cb (ctx->zio[1], forkzio_close_cb);
    if (zio_zloop_attach (ctx->zio[1], zloop) < 0)
        err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[1]));
    ctx->readers++;

    /* child stderr => zs
     */
    ctx->zio[2] = zio_pipe_reader_create ("stderr", zs, ctx);
    zio_set_close_cb (ctx->zio[2], forkzio_close_cb);
    if (zio_zloop_attach (ctx->zio[2], zloop) < 0)
        err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[2]));
    ctx->readers++;

    pid = forkzio_fork (ctx);
    (void)zloop_start (zloop);
    forkzio_wait (pid);

    zio_destroy (ctx->zio[0]);
    zio_destroy (ctx->zio[1]);
    zio_destroy (ctx->zio[2]);

    zstr_send (zs, ""); /* signify EOF by sending an empty message */
}

static void forkzio_pty_thd (void *args, zctx_t *zctx, void *zs)
{
    forkzio_t ctx = args;
    zmq_pollitem_t zp = { .fd = -1, .socket = zs, .events = ZMQ_POLLIN };
    zloop_t *zloop;
    pid_t pid;
    int ptyfd;

    if (!(zloop = zloop_new ()))
        oom ();

    switch ((pid = forkpty (&ptyfd, NULL, NULL, NULL))) {
        case -1: /* error */
            err_exit ("forkpty");
        case 0: /* child */
            (void)execvp (ctx->av[0], ctx->av);
            err_exit ("%s", ctx->av[0]);
        default: /* parent */
            break;
    }

    /* Data read from zs is written to pty master
     */
    zloop_poller (zloop, &zp, (zloop_fn *)forkzio_zsock_cb, ctx);
    ctx->zio[0] = zio_writer_create ("stdin", ptyfd, NULL);
    zio_set_unbuffered (ctx->zio[0]);
    if (zio_zloop_attach (ctx->zio[0], zloop) < 0)
        err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[0]));

    /* Data read from pty master is written to zs
     */
    ctx->zio[1] = zio_reader_create ("stdout", ptyfd, zs, ctx);
    zio_set_unbuffered (ctx->zio[1]);
    zio_set_close_cb (ctx->zio[1], forkzio_close_cb);
    if (zio_zloop_attach (ctx->zio[1], zloop) < 0)
        err_exit ("zio_zloop_attach %s", zio_name (ctx->zio[1]));
    ctx->readers++;

    (void)zloop_start (zloop);
    forkzio_wait (pid);

    zio_destroy (ctx->zio[0]);
    zio_destroy (ctx->zio[1]);

    zstr_send (zs, ""); /* signify EOF by sending an empty message */
}

forkzio_t forkzio_open (zctx_t *zctx, int ac, char **av, int flags)
{
    zthread_attached_fn *thd = forkzio_pipe_thd;
    forkzio_t ctx = xzmalloc (sizeof (*ctx));

    ctx->ac = ac;
    ctx->av = av;
    ctx->zctx = zctx;
    ctx->flags = flags;

    if ((ctx->flags & FORKZIO_FLAG_PTY))
        thd = forkzio_pty_thd;
    if (!(ctx->zs = zthread_fork (zctx, thd, ctx))) {
        free (ctx);
        ctx = NULL;
    }
    return ctx;
}
Ejemplo n.º 23
0
///
//  Register low-level libzmq pollitem with the reactor. When the pollitem  
//  is ready, will call the handler, passing the arg. Returns 0 if OK, -1   
//  if there was an error. If you register the pollitem more than once, each
//  instance will invoke its corresponding handler. A pollitem with         
//  socket=NULL and fd=0 means 'poll on FD zero'.                           
int QmlZloop::poller (zmq_pollitem_t *item, zloop_fn handler, void *arg) {
    return zloop_poller (self, item, handler, arg);
};
Ejemplo n.º 24
0
int main (int argc, char *argv [])
{
    clonesrv_t *self = (clonesrv_t *) zmalloc (sizeof (clonesrv_t));
    if (argc == 2 && streq (argv [1], "-p")) {
        zclock_log ("I: primary master, waiting for backup (slave)");
        self->bstar = bstar_new (BSTAR_PRIMARY, "tcp://*:5003",
                                 "tcp://localhost:5004");
        bstar_voter (self->bstar, "tcp://*:5556", ZMQ_ROUTER, s_snapshots, self);
        self->port = 5556;
        self->peer = 5566;
        self->primary = TRUE;
    }
    else
    if (argc == 2 && streq (argv [1], "-b")) {
        zclock_log ("I: backup slave, waiting for primary (master)");
        self->bstar = bstar_new (BSTAR_BACKUP, "tcp://*:5004",
                                 "tcp://localhost:5003");
        bstar_voter (self->bstar, "tcp://*:5566", ZMQ_ROUTER, s_snapshots, self);
        self->port = 5566;
        self->peer = 5556;
        self->primary = FALSE;
    }
    else {
        printf ("Usage: clonesrv4 { -p | -b }\n");
        free (self);
        exit (0);
    }
    //  Primary server will become first master
    if (self->primary)
        self->kvmap = zhash_new ();

    self->ctx = zctx_new ();
    self->pending = zlist_new ();
    bstar_set_verbose (self->bstar, TRUE);

    //  Set up our clone server sockets
    self->publisher = zsocket_new (self->ctx, ZMQ_PUB);
    self->collector = zsocket_new (self->ctx, ZMQ_SUB);
    zsockopt_set_subscribe (self->collector, "");
    zsocket_bind (self->publisher, "tcp://*:%d", self->port + 1);
    zsocket_bind (self->collector, "tcp://*:%d", self->port + 2);

    //  Set up our own clone client interface to peer
    self->subscriber = zsocket_new (self->ctx, ZMQ_SUB);
    zsockopt_set_subscribe (self->subscriber, "");
    zsocket_connect (self->subscriber, "tcp://localhost:%d", self->peer + 1);

    //  Register state change handlers
    bstar_new_master (self->bstar, s_new_master, self);
    bstar_new_slave (self->bstar, s_new_slave, self);

    //  Register our other handlers with the bstar reactor
    zmq_pollitem_t poller = { self->collector, 0, ZMQ_POLLIN };
    zloop_poller (bstar_zloop (self->bstar), &poller, s_collector, self);
    zloop_timer  (bstar_zloop (self->bstar), 1000, 0, s_flush_ttl, self);
    zloop_timer  (bstar_zloop (self->bstar), 1000, 0, s_send_hugz, self);

    //  Start the Bstar reactor
    bstar_start (self->bstar);

    //  Interrupted, so shut down
    while (zlist_size (self->pending)) {
        kvmsg_t *kvmsg = (kvmsg_t *) zlist_pop (self->pending);
        kvmsg_destroy (&kvmsg);
    }
    zlist_destroy (&self->pending);
    bstar_destroy (&self->bstar);
    zhash_destroy (&self->kvmap);
    zctx_destroy (&self->ctx);
    free (self);

    return 0;
}
Ejemplo n.º 25
0
Archivo: vtx_tcp.c Proyecto: imatix/vtx
static binding_t *
binding_require (vocket_t *vocket, char *address)
{
    assert (vocket);
    binding_t *self = (binding_t *) zhash_lookup (vocket->binding_hash, address);

    if (self == NULL) {
        //  Create new binding for this hostname:port address
        self = (binding_t *) zmalloc (sizeof (binding_t));
        self->vocket = vocket;
        self->driver = vocket->driver;
        self->address = strdup (address);
        driver_t *driver = self->driver;

        //  Split port number off address
        char *port = strchr (address, ':');
        assert (port);
        *port++ = 0;

        //* Start transport-specific work
        //  Create new bound TCP socket handle
        self->handle = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (self->handle == -1)
            derp ("socket");

        //  Get sockaddr_in structure for address
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons (atoi (port));

        //  Bind handle to specific local address, or *
        if (streq (address, "*"))
            addr.sin_addr.s_addr = htonl (INADDR_ANY);
        else
        if (inet_aton (address, &addr.sin_addr) == 0) {
            zclock_log ("E: bind failed: invalid address '%s'", address);
            self->exception = TRUE;
        }
        if (!self->exception) {
#           ifndef __WINDOWS__
            //  On POSIX systems we need to set SO_REUSEADDR to reuse an
            //  address without a 5-minute timeout. On win32 this option
            //  lets you bind to an in-use address, so we do not do that.
            int reuse = 1;
            setsockopt (self->handle, SOL_SOCKET, SO_REUSEADDR,
                (void *) &reuse, sizeof (reuse));
#           endif
            if (bind (self->handle,
                (const struct sockaddr *) &addr, IN_ADDR_SIZE) == -1) {
                zclock_log ("E: bind failed: '%s'", strerror (errno));
                self->exception = TRUE;
            }
            else
            if (listen (self->handle, VTX_TCP_BACKLOG)) {
                zclock_log ("E: listen failed: '%s'", strerror (errno));
                self->exception = TRUE;
            }
        }
        if (self->exception)
            close (self->handle);
        else {
            //  Ask reactor to start monitoring this binding handle
            zmq_pollitem_t item = { NULL, self->handle, ZMQ_POLLIN, 0 };
            zloop_poller (driver->loop, &item, s_binding_input, vocket);
        }
        //* End transport-specific work
        if (self->exception) {
            free (self->address);
            free (self);
            self = NULL;
        }
        else {
            //  Store new binding in vocket containers
            zhash_insert (vocket->binding_hash, address, self);
            zhash_freefn (vocket->binding_hash, address, binding_delete);
            if (driver->verbose)
                zclock_log ("I: (tcp) create binding to %s", self->address);
        }
    }
    return self;
}
Ejemplo n.º 26
0
int main (int argc, char *argv [])
{
    clonesrv_t *self = (clonesrv_t *) zmalloc (sizeof (clonesrv_t));
    if (argc == 2 && streq (argv [1], "-p")) {
        zclock_log ("I: primary active, waiting for backup (passive)");
        self->bstar = bstar_new (BSTAR_PRIMARY, "tcp://*:5003",
                                 "tcp://localhost:5004");
        bstar_voter (self->bstar, "tcp://*:5556",
                     ZMQ_ROUTER, s_snapshots, self);
        self->port = 5556;
        self->peer = 5566;
        self->primary = true;
    }
    else
    if (argc == 2 && streq (argv [1], "-b")) {
        zclock_log ("I: backup passive, waiting for primary (active)");
        self->bstar = bstar_new (BSTAR_BACKUP, "tcp://*:5004",
                                 "tcp://localhost:5003");
        bstar_voter (self->bstar, "tcp://*:5566",
                     ZMQ_ROUTER, s_snapshots, self);
        self->port = 5566;
        self->peer = 5556;
        self->primary = false;
    }
    else {
        printf ("Usage: clonesrv4 { -p | -b }\n");
        free (self);
        exit (0);
    }
    //  Primary server will become first active
    if (self->primary)
        self->kvmap = zhash_new ();

    self->ctx = zctx_new ();
    self->pending = zlist_new ();
    bstar_set_verbose (self->bstar, true);

    //  Set up our clone server sockets
    self->publisher = zsocket_new (self->ctx, ZMQ_PUB);
    self->collector = zsocket_new (self->ctx, ZMQ_SUB);
    zsocket_set_subscribe (self->collector, "");
    zsocket_bind (self->publisher, "tcp://*:%d", self->port + 1);
    zsocket_bind (self->collector, "tcp://*:%d", self->port + 2);

    //  Set up our own clone client interface to peer
    self->subscriber = zsocket_new (self->ctx, ZMQ_SUB);
    zsocket_set_subscribe (self->subscriber, "");
    zsocket_connect (self->subscriber,
                     "tcp://localhost:%d", self->peer + 1);

    //  .split main task body
    //  After we've setup our sockets, we register our binary star
    //  event handlers, and then start the bstar reactor. This finishes
    //  when the user presses Ctrl-C or when the process receives a SIGINT
    //  interrupt:

    //  Register state change handlers
    bstar_new_active (self->bstar, s_new_active, self);
    bstar_new_passive (self->bstar, s_new_passive, self);

    //  Register our other handlers with the bstar reactor
    zmq_pollitem_t poller = { self->collector, 0, ZMQ_POLLIN };
    zloop_poller (bstar_zloop (self->bstar), &poller, s_collector, self);
    zloop_timer  (bstar_zloop (self->bstar), 1000, 0, s_flush_ttl, self);
    zloop_timer  (bstar_zloop (self->bstar), 1000, 0, s_send_hugz, self);

    //  Start the bstar reactor
    bstar_start (self->bstar);

    //  Interrupted, so shut down
    while (zlist_size (self->pending)) {
        kvmsg_t *kvmsg = (kvmsg_t *) zlist_pop (self->pending);
        kvmsg_destroy (&kvmsg);
    }
    zlist_destroy (&self->pending);
    bstar_destroy (&self->bstar);
    zhash_destroy (&self->kvmap);
    zctx_destroy (&self->ctx);
    free (self);

    return 0;
}
Ejemplo n.º 27
0
///
//  Register low-level libzmq pollitem with the reactor. When the pollitem  
//  is ready, will call the handler, passing the arg. Returns 0 if OK, -1   
//  if there was an error. If you register the pollitem more than once, each
//  instance will invoke its corresponding handler. A pollitem with         
//  socket=NULL and fd=0 means 'poll on FD zero'.                           
int QZloop::poller (zmq_pollitem_t *item, zloop_fn handler, void *arg)
{
    int rv = zloop_poller (self, item, handler, arg);
    return rv;
}
Ejemplo n.º 28
0
maltcp_ctx_t *maltcp_ctx_new(mal_ctx_t *mal_ctx,
    char *hostname, char *port,
    maltcp_header_t *maltcp_header,
    // TODO: no longer used
    bool verbose) {
  maltcp_ctx_t *self = (maltcp_ctx_t *) malloc(sizeof(maltcp_ctx_t));
  if (!self)
    return NULL;

  self->mal_ctx = mal_ctx;
  self->hostname = hostname;
  self->port = port;
  self->maltcp_header = maltcp_header;

  self->encoder = malbinary_encoder_new(true);
  self->decoder = malbinary_decoder_new(true);

  self->root_uri = (char *) malloc(strlen(hostname) + strlen(port) + 10 + 1);
  sprintf((char*) self->root_uri, "%s%s:%s", MALTCP_URI, hostname, port);
  clog_debug(maltcp_logger, "maltcp_ctx_new: root_uri=%s\n", self->root_uri);

  zctx_t *zmq_ctx = zctx_new();
  self->zmq_ctx = zmq_ctx;

  self->cnx_table = zhash_new();

  // Creates the TCP listening socket
  int listen = maltcp_ctx_server_socket_create(atoi(port), BACKLOG);
  //assert(listen >= 0);
  if (listen < 0) {
    clog_error(maltcp_logger, "EXCEPTION:: maltcp_ctx_new: listen = %d\n", listen);
    return NULL;
  }

  self->mal_socket = listen;
  clog_debug(maltcp_logger, "maltcp_ctx: ptp listening to: %s\n", port);

  //inproc
  void *endpoints_socket = zsocket_new(zmq_ctx, ZMQ_ROUTER);
  self->endpoints_socket = endpoints_socket;
  zsocket_bind(endpoints_socket, ZLOOP_ENDPOINTS_SOCKET_URI);

  zloop_t *zloop = zloop_new();
  // TODO (AF): It seems that adding poller from outside of handler is not correctly
  // supported by ZMQ. We should provide an inproc socket allowing to add the needed
  // poller. However it seems that a timer regularly awaking the zloop corrects this
  // issue.
  zloop_timer(zloop, 100, 0, zloop_timer_handle, self);
//  zloop_set_verbose(zloop, true);
  self->zloop = zloop;

  zmq_pollitem_t poller = { NULL, listen, ZMQ_POLLIN };
  int rc = zloop_poller(zloop, &poller, maltcp_ctx_socket_accept, self);
  assert(rc == 0);

  mal_ctx_set_binding(
      mal_ctx, self,
      maltcp_ctx_create_uri,
      maltcp_ctx_create_endpoint, maltcp_ctx_destroy_endpoint,
      maltcp_ctx_create_poller, maltcp_ctx_destroy_poller,
      maltcp_ctx_poller_add_endpoint, maltcp_ctx_poller_del_endpoint,
      maltcp_ctx_send_message, maltcp_ctx_recv_message,
      maltcp_ctx_poller_wait,
      maltcp_ctx_destroy_message,
      maltcp_ctx_start,
      maltcp_ctx_stop,
      maltcp_ctx_destroy);

  return self;
}
Ejemplo n.º 29
0
void PrimeWorker::Work(zctx_t *ctx, void *pipe) {
	
	printf("PrimeWorker started.\n");
	
	mBackend = zsocket_new(ctx, ZMQ_DEALER);
	void* frontend = zsocket_new(ctx, ZMQ_DEALER);
	void* input = zsocket_new(ctx, ZMQ_SUB);
	mServer = zsocket_new(ctx, ZMQ_ROUTER);
	mSignals = zsocket_new(ctx, ZMQ_PUB);
	
	zsocket_set_sndhwm(mBackend, 1*1000*1000);
	
	int err = 0;
	err = zsocket_bind(mServer, "tcp://*:%d", mServerPort);
	if(!err)
		printf("zsocket_bind(mServer, tcp://*:*) failed.\n");
	
	err = zsocket_bind(mSignals, "tcp://*:%d", mSignalPort);
	if(!err)
		printf("zsocket_bind(mSignals, tcp://*:*) failed.\n");
	
	printf("PrimeWorker: mServerPort=%d mSignalPort=%d\n", mServerPort, mSignalPort);
	
	err = zsocket_connect(mBackend, "tcp://localhost:8888");
	assert(!err);
	
	err = zsocket_connect(frontend, "tcp://localhost:7777");
	assert(!err);
	
	err = zsocket_connect(input, "inproc://bitcoin");
	assert(!err);
	
	const char one[2] = {1, 0};
	zsocket_set_subscribe(input, one);
	
	zloop_t* wloop = zloop_new();
	
	zmq_pollitem_t item_input = {input, 0, ZMQ_POLLIN, 0};
	err = zloop_poller(wloop, &item_input, &PrimeWorker::InvokeInput, this);
	assert(!err);
	
	zmq_pollitem_t item_server = {mServer, 0, ZMQ_POLLIN, 0};
	err = zloop_poller(wloop, &item_server, &PrimeWorker::InvokeRequest, this);
	assert(!err);
	
	zmq_pollitem_t item_frontend = {frontend, 0, ZMQ_POLLIN, 0};
	err = zloop_poller(wloop, &item_frontend, &PrimeWorker::InvokeRequest, this);
	assert(!err);
	
	err = zloop_timer(wloop, 60000, 0, &PrimeWorker::InvokeTimerFunc, this);
	assert(err >= 0);
	
	zsocket_signal(pipe);
	
	zloop_start(wloop);
	
	zloop_destroy(&wloop);
	
	zsocket_destroy(ctx, mServer);
	zsocket_destroy(ctx, mSignals);
	zsocket_destroy(ctx, mBackend);
	zsocket_destroy(ctx, frontend);
	zsocket_destroy(ctx, input);
	
	zsocket_signal(pipe);
	
	printf("PrimeWorker exited.\n");
	
}
Ejemplo n.º 30
0
int main(void) {
	
	gBlock.set_height(0);
	gClientName = sysinfo::GetClientName();
	gClientID = sysinfo::GetClientID();
	gInstanceID = gClientID * (unsigned)time(0);
	srand(gInstanceID);
	
	std::string frontHost;
	unsigned frontPort;
	
	Configuration* cfg = Configuration::create();
	try{
		cfg->parse("config.txt");
		frontHost = cfg->lookupString("", "server", "localhost");
		frontPort = cfg->lookupInt("", "port", 6666);
		gAddr = cfg->lookupString("", "address", "");
		gClientName = cfg->lookupString("", "name", gClientName.c_str());
	}catch(const ConfigurationException& ex){
		printf("ERROR: %s\n", ex.c_str());
		printf("hit return to exit...\n");
		std::string line;
		std::getline(std::cin, line);
		exit(EXIT_FAILURE);
	}
	
	if(!gClientName.size())
		gClientName = sysinfo::GetClientName();
	
	printf("madPrimeMiner-v%d.%d\n", gClientVersion/10, gClientVersion%10);
	printf("ClientName = '%s'  ClientID = %u  InstanceID = %u\n", gClientName.c_str(), gClientID, gInstanceID);
	printf("Address = '%s'\n", gAddr.c_str());
	
	if(!gAddr.size()){
		printf("ERROR: address not specified in config.txt\n");
		printf("hit return to exit...\n");
		std::string line;
		std::getline(std::cin, line);
		exit(EXIT_FAILURE);
	}
	
	gCtx = zctx_new();
	
	gWorkers = zsocket_new(gCtx, ZMQ_PULL);
	zsocket_bind(gWorkers, "inproc://shares");
	
	gClient = new XPMClient(gCtx);
	gExit = !gClient->Initialize(cfg);
	
	while(!gExit){
		
		printf("Connecting to frontend: %s:%d ...\n", frontHost.c_str(), frontPort);
		
		gBlock.Clear();
		proto::Reply rep;
		gExit = true;
		
		while(gExit){
			
			zsocket_destroy(gCtx, gFrontend);
			gFrontend = zsocket_new(gCtx, ZMQ_DEALER);
			
			int err = zsocket_connect(gFrontend, "tcp://%s:%d", frontHost.c_str(), frontPort);
			if(err){
				printf("ERROR: invalid hostname and/or port.\n");
				exit(EXIT_FAILURE);
			}
			
			proto::Request req;
			req.set_type(proto::Request::CONNECT);
			req.set_reqid(++gNextReqID);
			req.set_version(gClientVersion);
			req.set_height(0);
			
			GetNewReqNonce(req);
			Send(req, gFrontend);
			
			bool ready = zsocket_poll(gFrontend, 3*1000);
			
			if(zctx_interrupted)
				break;
			
			if(!ready)
				continue;
			
			Receive(rep, gFrontend);
			
			if(rep.error() != proto::Reply::NONE){
				printf("ERROR: %s\n", proto::Reply::ErrType_Name(rep.error()).c_str());
				if(rep.has_errstr())
					printf("Message from server: %s\n", rep.errstr().c_str());
			}
			
			if(!rep.has_sinfo())
				break;
			
			gServerInfo = rep.sinfo();
			
			bool ret = false;
			ret |= !ConnectBitcoin();
			ret |= !ConnectSignals();
			if(ret)
				break;
			
			gExit = false;
			
		}
		
		zsocket_disconnect(gFrontend, "tcp://%s:%d", frontHost.c_str(), frontPort);
		
		if(gExit)
			break;
		
		zloop_t* wloop = zloop_new();
		
		zmq_pollitem_t item_server = {gServer, 0, ZMQ_POLLIN, 0};
		int err = zloop_poller(wloop, &item_server, &HandleReply, 0);
		assert(!err);
		
		zmq_pollitem_t item_signals = {gSignals, 0, ZMQ_POLLIN, 0};
		err = zloop_poller(wloop, &item_signals, &HandleSignal, 0);
		assert(!err);
		
		zmq_pollitem_t item_workers = {gWorkers, 0, ZMQ_POLLIN, 0};
		err = zloop_poller(wloop, &item_workers, &HandleWorkers, 0);
		assert(!err);
		
		err = zloop_timer(wloop, 60*1000, 0, &HandleTimer, 0);
		assert(err >= 0);
		
		gHeartBeat = true;
		gExit = true;
		
		if(rep.has_block())
			HandleNewBlock(rep.block());
		else
			RequestWork();
		
		gClient->Toggle();
		zloop_start(wloop);
		
		gClient->Toggle();
		zloop_destroy(&wloop);
		
		zsocket_destroy(gCtx, gServer);
		zsocket_destroy(gCtx, gSignals);
		
		gServer = 0;
		gSignals = 0;
		
	}
	
	delete gClient;
	
	zsocket_destroy(gCtx, gWorkers);
	zsocket_destroy(gCtx, gFrontend);
	zctx_destroy(&gCtx);
	
	return EXIT_SUCCESS;
	
}