Exemple #1
0
static void
deregister_the_client (client_t *self)
{
    if (*self->address)
        zsys_info ("client address='%s' - de-registering", self->address);

    //  Cancel all stream subscriptions
    stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL);
    while (stream) {
        zsock_send (stream->actor, "sp", "CANCEL", self);
        stream = (stream_t *) zlistx_detach (self->readers, NULL);
    }
    //  Cancel all service offerings
    service_t *service = (service_t *) zhashx_first (self->server->services);
    while (service) {
        offer_t *offer = (offer_t *) zlistx_first (service->offers);
        while (offer) {
            if (offer->client == self)
                zlistx_delete (service->offers, zlistx_cursor (service->offers));
            offer = (offer_t *) zlistx_next (service->offers);
        }
        service = (service_t *) zhashx_next (self->server->services);
    }
    if (*self->address)
        zhashx_delete (self->server->clients, self->address);
    mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS);
}
Exemple #2
0
static void
deregister_the_client (client_t *self)
{
	// If the client never sent CONNECTION_OPEN then self->address was
	// never set, so avoid trying to dereference it.  Nothing needs to
    // be cleaned up.
    if (self->address) {
        if (*self->address)
            zsys_info ("client %u address='%s' - de-registering", self->unique_id, self->address);

        //  Cancel all stream subscriptions
        stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL);
        while (stream) {
            zsock_send (stream->actor, "sp", "CANCEL", self);
            stream = (stream_t *) zlistx_detach (self->readers, NULL);
        }
        //  Cancel all service offerings
        service_t *service = (service_t *) zhashx_first (self->server->services);
        while (service) {
            offer_t *offer = (offer_t *) zlistx_first (service->offers);
            while (offer) {
                if (offer->client == self)
                    zlistx_delete (service->offers, zlistx_cursor (service->offers));
                offer = (offer_t *) zlistx_next (service->offers);
            }
            service = (service_t *) zhashx_next (self->server->services);
        }
        if (*self->address)
            zhashx_delete (self->server->clients, self->address);
    }
    mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS);
}
Exemple #3
0
void
zloop_ticket_delete (zloop_t *self, void *handle)
{
    s_ticket_t *ticket = (s_ticket_t *) handle;
    assert (ticket->tag == TICKET_TAG);
    zlistx_delete (self->tickets, ticket->list_handle);
}
Exemple #4
0
void
zlistx_purge (zlistx_t *self)
{
    assert (self);
    while (zlistx_size (self) > 0)
        zlistx_delete (self, NULL);
}
Exemple #5
0
void
zloop_poller_end (zloop_t *self, zmq_pollitem_t *item)
{
    assert (self);

    s_poller_t *poller = (s_poller_t *) zlistx_first (self->pollers);
    while (poller) {
        bool match = false;
        if (item->socket) {
            if (item->socket == poller->item.socket)
                match = true;
        }
        else {
            if (item->fd == poller->item.fd)
                match = true;
        }
        if (match) {
            zlistx_delete (self->pollers, poller->list_handle);
            //  Force rebuild to avoid reading from freed poller
            self->need_rebuild = true;
        }
        poller = (s_poller_t *) zlistx_next (self->pollers);
    }
    if (self->verbose)
        zsys_debug ("zloop: cancel %s poller (%p, %d)",
                    item->socket ? zsys_sockname (zsock_type (item->socket)) : "FD",
                    item->socket, item->fd);
}
Exemple #6
0
int
ztrie_remove_route (ztrie_t *self, const char *path)
{
    assert (self);
    ztrie_node_t *match = s_ztrie_parse_path (self, path, MODE_LOOKUP);
    //  The path did match a node which is endpoint to a route
    if (match && match->endpoint) {
        //  This node is part of other routes, thus it cannot destroy it
        if (zlistx_size (match->children) > 0) {
            match->endpoint = false;
            if (match->data && match->destroy_data_fn)
                (match->destroy_data_fn) (&match->data);
        }
        //  If this node is not part of other routes, destroy it
        else {
            //  Delete match from parent's children before destroying
            void *handle = zlistx_find (match->parent->children, match);
            assert (handle);
            zlistx_delete (match->parent->children, handle);
            s_ztrie_node_destroy (&match);
        }
        return 0;
    }
    //  If there is no match or the match is not endpoint to a route, fail
    else
        return -1;
}
Exemple #7
0
static void
s_stream_engine_cancel (stream_engine_t *self, void *client)
{
    selector_t *selector = (selector_t *) zlistx_first (self->selectors);
    while (selector) {
        void *handle = zlistx_find (selector->clients, client);
        if (handle)
            zlistx_delete (selector->clients, handle);
        selector = (selector_t *) zlistx_next (self->selectors);
    }
}
Exemple #8
0
static void
s_timer_remove (zloop_t *self, int timer_id)
{
    s_timer_t *timer = (s_timer_t *) zlistx_first (self->timers);
    while (timer) {
        if (timer->timer_id == timer_id) {
            zlistx_delete (self->timers, timer->list_handle);
            break;
        }
        timer = (s_timer_t *) zlistx_next (self->timers);
    }
}
Exemple #9
0
void
zloop_reader_end (zloop_t *self, zsock_t *sock)
{
    assert (self);
    assert (sock);

    s_reader_t *reader = (s_reader_t *) zlistx_first (self->readers);
    while (reader) {
        if (reader->sock == sock) {
            zlistx_delete (self->readers, reader->list_handle);
            self->need_rebuild = true;
        }
        reader = (s_reader_t *) zlistx_next (self->readers);
    }
    if (self->verbose)
        zsys_debug ("zloop: cancel %s reader", zsock_type_str (sock));
}
Exemple #10
0
void
mlm_server_test (bool verbose)
{
    printf (" * mlm_server: ");
    if (verbose)
        printf ("\n");

    //  @selftest
    zactor_t *server = zactor_new (mlm_server, "mlm_server_test");
    if (verbose)
        zstr_send (server, "VERBOSE");
    zstr_sendx (server, "BIND", "tcp://127.0.0.1:*", NULL);
    zstr_sendx (server, "PORT", NULL);
    char *command, *port;
    int rc = zstr_recvx (server, &command, &port, NULL);
    assert (rc == 2);
    assert (streq (command, "PORT"));
    assert (strlen (port) > 0 && strlen (port) < 6);
    assert (!streq (port, "-1"));

    zsock_t *reader = zsock_new (ZMQ_DEALER);
    assert (reader);
    zsock_connect (reader, "tcp://127.0.0.1:%s", port);
    zsock_set_rcvtimeo (reader, 500);

    mlm_proto_t *proto = mlm_proto_new ();

    //  Server insists that connection starts properly
    mlm_proto_set_id (proto, MLM_PROTO_STREAM_WRITE);
    mlm_proto_send (proto, reader);
    zclock_sleep (500); //  to calm things down && make memcheck pass. Thanks @malanka
    mlm_proto_recv (proto, reader);
    zclock_sleep (500); //  detto as above
    assert (mlm_proto_id (proto) == MLM_PROTO_ERROR);
    assert (mlm_proto_status_code (proto) == MLM_PROTO_COMMAND_INVALID);

    //  Now do a stream publish-subscribe test
    zsock_t *writer = zsock_new (ZMQ_DEALER);
    assert (writer);
    zsock_connect (writer, "tcp://127.0.0.1:%s", port);
    zsock_set_rcvtimeo (reader, 500);

    //  Open connections from both reader and writer
    mlm_proto_set_id (proto, MLM_PROTO_CONNECTION_OPEN);
    mlm_proto_send (proto, reader);
    mlm_proto_recv (proto, reader);
    assert (mlm_proto_id (proto) == MLM_PROTO_OK);

    mlm_proto_set_id (proto, MLM_PROTO_CONNECTION_OPEN);
    mlm_proto_send (proto, writer);
    mlm_proto_recv (proto, writer);
    assert (mlm_proto_id (proto) == MLM_PROTO_OK);

    //  Prepare to write and read a "weather" stream
    mlm_proto_set_id (proto, MLM_PROTO_STREAM_WRITE);
    mlm_proto_set_stream (proto, "weather");
    mlm_proto_send (proto, writer);
    mlm_proto_recv (proto, writer);
    assert (mlm_proto_id (proto) == MLM_PROTO_OK);

    mlm_proto_set_id (proto, MLM_PROTO_STREAM_READ);
    mlm_proto_set_pattern (proto, "temp.*");
    mlm_proto_send (proto, reader);
    mlm_proto_recv (proto, reader);
    assert (mlm_proto_id (proto) == MLM_PROTO_OK);

    //  Now send some weather data, with null contents
    mlm_proto_set_id (proto, MLM_PROTO_STREAM_SEND);
    mlm_proto_set_subject (proto, "temp.moscow");
    mlm_proto_send (proto, writer);
    mlm_proto_set_subject (proto, "rain.moscow");
    mlm_proto_send (proto, writer);
    mlm_proto_set_subject (proto, "temp.chicago");
    mlm_proto_send (proto, writer);
    mlm_proto_set_subject (proto, "rain.chicago");
    mlm_proto_send (proto, writer);
    mlm_proto_set_subject (proto, "temp.london");
    mlm_proto_send (proto, writer);
    mlm_proto_set_subject (proto, "rain.london");
    mlm_proto_send (proto, writer);

    //  We should receive exactly three deliveries, in order
    mlm_proto_recv (proto, reader);
    assert (mlm_proto_id (proto) == MLM_PROTO_STREAM_DELIVER);
    assert (streq (mlm_proto_subject (proto), "temp.moscow"));

    mlm_proto_recv (proto, reader);
    assert (mlm_proto_id (proto) == MLM_PROTO_STREAM_DELIVER);
    assert (streq (mlm_proto_subject (proto), "temp.chicago"));

    mlm_proto_recv (proto, reader);
    assert (mlm_proto_id (proto) == MLM_PROTO_STREAM_DELIVER);
    assert (streq (mlm_proto_subject (proto), "temp.london"));

    mlm_proto_destroy (&proto);

    //  Finished, we can clean up
    zsock_destroy (&writer);
    zsock_destroy (&reader);
    zactor_destroy (&server);
    zstr_free (&port);
    zstr_free (&command);

    // Test Case:
    //      CLIENTLIST command
    {
        const char *endpoint = "inproc://mlm_server_clientlist_test";
        zactor_t *server = zactor_new (mlm_server, "mlm_server_clientlist_test");
        if (verbose)
            zstr_send (server, "VERBOSE");
        zstr_sendx (server, "BIND", endpoint, NULL);

        mlm_client_t *client_1 = mlm_client_new ();
        int rv = mlm_client_connect (client_1, endpoint, 1000, "Karol");
        assert (rv >= 0);

        mlm_client_t *client_2 = mlm_client_new ();
        rv = mlm_client_connect (client_2, endpoint, 1000, "Tomas");
        assert (rv >= 0);

        mlm_client_t *client_3 = mlm_client_new ();
        rv = mlm_client_connect (client_3, endpoint, 1000, "Alenka");
        assert (rv >= 0);

        zclock_sleep (500);

        zstr_sendx (server, "CLIENTLIST", NULL);

        zmsg_t *message = zmsg_recv (server);
        assert (message);
        assert (zmsg_size (message) == 4);

        char *pop = zmsg_popstr (message);
        assert (streq (pop, "CLIENTLIST"));
        zstr_free (&pop);

        zlistx_t *expected_names = zlistx_new ();
        assert (expected_names);
        zlistx_set_destructor (expected_names, (czmq_destructor *) zstr_free);
        zlistx_set_duplicator (expected_names, (czmq_duplicator *) strdup);
        zlistx_set_comparator (expected_names, (czmq_comparator *) strcmp);

        zlistx_add_end (expected_names, (void *) "Karol");
        zlistx_add_end (expected_names, (void *) "Tomas");
        zlistx_add_end (expected_names, (void *) "Alenka");

        pop = zmsg_popstr (message);
        assert (pop);
        void *handle = zlistx_find (expected_names, pop);
        assert (handle);
        rv = zlistx_delete (expected_names, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_names, pop);
        assert (handle);
        rv = zlistx_delete (expected_names, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_names, pop);
        assert (handle);
        rv = zlistx_delete (expected_names, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop == NULL);
        assert (zlistx_size (expected_names) == 0);


        zmsg_destroy (&message);

        // remove a client Karol
        mlm_client_destroy (&client_1);

        zlistx_add_end (expected_names, (void *) "Tomas");
        zlistx_add_end (expected_names, (void *) "Alenka");

        zstr_sendx (server, "CLIENTLIST", NULL);
        zclock_sleep (100);

        message = zmsg_recv (server);
        assert (message);
        assert (zmsg_size (message) == 3);

        pop = zmsg_popstr (message);
        assert (streq (pop, "CLIENTLIST"));
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_names, pop);
        assert (handle);
        rv = zlistx_delete (expected_names, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_names, pop);
        assert (handle);
        rv = zlistx_delete (expected_names, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop == NULL);
        assert (zlistx_size (expected_names) == 0);

        zlistx_destroy (&expected_names);
        zmsg_destroy (&message);

        mlm_client_destroy (&client_2);
        mlm_client_destroy (&client_3);
        zactor_destroy (&server);
    }

    // Test Case:
    //      STREAMLIST command
    {
        const char *endpoint = "inproc://mlm_server_streamlist_test";
        zactor_t *server = zactor_new (mlm_server, "mlm_server_streamlist_test");
        if (verbose)
            zstr_send (server, "VERBOSE");
        zstr_sendx (server, "BIND", endpoint, NULL);

        mlm_client_t *client_1 = mlm_client_new ();
        int rv = mlm_client_connect (client_1, endpoint, 1000, "Karol");
        assert (rv != -1);
        rv = mlm_client_set_producer (client_1, "STREAM_1");
        assert (rv != -1);

        mlm_client_t *client_2 = mlm_client_new ();
        rv = mlm_client_connect (client_2, endpoint, 1000, "Tomas");
        assert (rv != -1);
        rv = mlm_client_set_producer (client_2, "STREAM_2");
        assert (rv != -1);

        mlm_client_t *client_3 = mlm_client_new ();
        rv = mlm_client_connect (client_3, endpoint, 1000, "Alenka");
        assert (rv != -1);
        rv = mlm_client_set_consumer (client_3, "STREAM_2", ".*");
        assert (rv != -1);

        zclock_sleep (100);

        zlistx_t *expected_streams = zlistx_new ();
        assert (expected_streams);
        zlistx_set_destructor (expected_streams, (czmq_destructor *) zstr_free);
        zlistx_set_duplicator (expected_streams, (czmq_duplicator *) strdup);
        zlistx_set_comparator (expected_streams, (czmq_comparator *) strcmp);

        zlistx_add_end (expected_streams, (void *) "STREAM_1");
        zlistx_add_end (expected_streams, (void *) "STREAM_2");

        zstr_sendx (server, "STREAMLIST", NULL);

        zmsg_t *message = zmsg_recv (server);
        assert (message);
        assert (zmsg_size (message) == 3);

        char *pop = zmsg_popstr (message);
        assert (streq (pop, "STREAMLIST"));
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        void *handle = zlistx_find (expected_streams, pop);
        assert (handle);
        rv = zlistx_delete (expected_streams, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_streams, pop);
        assert (handle);
        rv = zlistx_delete (expected_streams, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop == NULL);
        assert (zlistx_size (expected_streams) == 0);

        zmsg_destroy (&message);

        //  NOTE: Currently when producer disconnects, malamute does not destroy the stream
        //  Therefore it doesn't make sense to test removal of streams, but addition
        mlm_client_t *client_4 = mlm_client_new ();
        rv = mlm_client_connect (client_4, endpoint, 1000, "Michal");
        assert (rv >= 0);
        rv = mlm_client_set_producer (client_4, "New stream");
        assert (rv >= 0);

        zlistx_add_end (expected_streams, (void *) "STREAM_1");
        zlistx_add_end (expected_streams, (void *) "STREAM_2");
        zlistx_add_end (expected_streams, (void *) "New stream");
        zclock_sleep (100);

        zstr_sendx (server, "STREAMLIST", NULL);
        zclock_sleep (100);

        message = zmsg_recv (server);
        assert (message);
        assert (zmsg_size (message) == 4);

        pop = zmsg_popstr (message);
        assert (streq (pop, "STREAMLIST"));
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_streams, pop);
        assert (handle);
        rv = zlistx_delete (expected_streams, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_streams, pop);
        assert (handle);
        rv = zlistx_delete (expected_streams, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop);
        handle = zlistx_find (expected_streams, pop);
        assert (handle);
        rv = zlistx_delete (expected_streams, handle);
        assert (rv == 0);
        zstr_free (&pop);

        pop = zmsg_popstr (message);
        assert (pop == NULL);
        assert (zlistx_size (expected_streams) == 0);

        zlistx_destroy (&expected_streams);
        zmsg_destroy (&message);

        mlm_client_destroy (&client_1);
        mlm_client_destroy (&client_2);
        mlm_client_destroy (&client_3);
        mlm_client_destroy (&client_4);
        zactor_destroy (&server);
    }

    // Regression Test Case:
    //      Segfault from deregistering zombie connection
    {
        const char *endpoint = "inproc://mlm_server_deregister_zombie_connection_test";
        zactor_t *server = zactor_new (mlm_server, "mlm_server_deregister_zombie_connection_test");
        if (verbose)
            zstr_send (server, "VERBOSE");
        zstr_sendx (server, "BIND", endpoint, NULL);
        zstr_sendx (server, "SET", "server/timeout", "3000", NULL); // 3 second client timeout

        zsock_t *reader = zsock_new (ZMQ_DEALER);
        assert (reader);
        zsock_connect (reader, "inproc://mlm_server_deregister_zombie_connection_test");
        zsock_set_rcvtimeo (reader, 500);

        mlm_proto_t *proto = mlm_proto_new ();

        // If the malamute server is restarted and clients have queued
        // up ping messages, the'll be sent before any
        // CONNECTION_OPEN.  The server eventually tries to deregister
        // this and (previously) would derefence a null pointer for
        // the client address.
        mlm_proto_set_id (proto, MLM_PROTO_CONNECTION_PING);
        mlm_proto_send (proto, reader);

        printf("Regression test for segfault due to leftover client messages after restart...\n");
        // Give the server more than 3 seconds to time out the client...
        zclock_sleep (3100);
        printf("passed\n");

        mlm_proto_destroy (&proto);
        zsock_destroy (&reader);
        zactor_destroy (&server);
    }

    {
        const char *endpoint = "inproc://mlm_server_disconnect_pending_stream_traffic";
        zactor_t *server = zactor_new (mlm_server, "mlm_server_disconnect_pending_stream_traffic");
        if (verbose) {
            zstr_send (server, "VERBOSE");
            printf("Regression test for use-after-free with pending stream traffic after disconnect\n");
        }
        zstr_sendx (server, "BIND", endpoint, NULL);

        mlm_client_t *producer = mlm_client_new ();
        assert (mlm_client_connect (producer, endpoint, 1000, "producer") >= 0);
        assert (mlm_client_set_producer (producer, "STREAM_TEST") >= 0);

        zstr_sendx (server, "SLOW_TEST_MODE", NULL);

        mlm_client_t *consumer = mlm_client_new ();
        assert (mlm_client_connect (consumer, endpoint, 1000, "consumer") >= 0);
        assert (mlm_client_set_consumer (consumer, "STREAM_TEST", ".*") >= 0);

        zmsg_t *msg = zmsg_new ();
        zmsg_addstr (msg, "world");
        assert (mlm_client_send (producer, "hello", &msg) >= 0);

        mlm_client_destroy (&consumer);

        zclock_sleep (2000);

        mlm_client_destroy (&producer);
        zactor_destroy (&server);
    }

    //  @end
    printf ("OK\n");
}
Exemple #11
0
static void handler (zsock_t *pipe, void *args) {
    curl_global_init(CURL_GLOBAL_ALL);
    CURLM *multi = curl_multi_init ();
    CURLSH *share = curl_share_init ();
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);

    long verbose = (*(bool *) args) ? 1L : 0L;
    long timeout = 30;
    CURLMcode code;

    SOCKET pipefd = zsock_fd (pipe);
    struct curl_waitfd waitfd = {pipefd, CURL_WAIT_POLLIN};

    //  List to hold pending curl handles, in case we are destroy the client
    //  while request are inprogress
    zlistx_t *pending_handles = zlistx_new ();
    zlistx_set_destructor (pending_handles, (zlistx_destructor_fn *) curl_destructor);

    zsock_signal (pipe, 0);

    bool terminated = false;
    while (!terminated) {
        int events = zsock_events (pipe);
        if ((events & ZMQ_POLLIN) == 0) {
            code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL);
            assert (code == CURLM_OK);
        }

        events = zsock_events (pipe);
        if (events & ZMQ_POLLIN) {
            char* command = zstr_recv (pipe);
            if (!command)
                break;          //  Interrupted

            //  All actors must handle $TERM in this way
            if (streq (command, "$TERM"))
                terminated = true;
            else if (streq (command, "GET")) {
                char *url;
                zlistx_t *headers;
                void *userp;
                int rc = zsock_recv (pipe, "slp", &url, &headers, &userp);
                assert (rc == 0);

                zchunk_t *data = zchunk_new (NULL, 100);
                assert (data);
                struct curl_slist *curl_headers = zlistx_to_slist (headers);
                CURL *curl = curl_easy_init ();
                zlistx_add_end (pending_handles, curl);
                http_request *request = (http_request *) zmalloc (sizeof (http_request));
                assert (request);
                request->userp = userp;
                request->curl = curl;
                request->data = data;
                request->headers = curl_headers;

                curl_easy_setopt (curl, CURLOPT_SHARE, share);
                curl_easy_setopt (curl, CURLOPT_TIMEOUT, timeout);
                curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose);
                curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers);
                curl_easy_setopt (curl, CURLOPT_URL, url);
                curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
                curl_easy_setopt (curl, CURLOPT_WRITEDATA, data);
                curl_easy_setopt (curl, CURLOPT_PRIVATE, request);

                code = curl_multi_add_handle (multi, curl);
                assert (code == CURLM_OK);
                zlistx_destroy (&headers);
                zstr_free (&url);
           }
           else {
               puts ("E: invalid message to actor");
               assert (false);
           }
           zstr_free (&command);
        }

        int still_running;
        code = curl_multi_perform (multi, &still_running);
        assert (code == CURLM_OK);

        int msgq = 0;
        struct CURLMsg *msg = curl_multi_info_read(multi, &msgq);

        while (msg) {
            if(msg->msg == CURLMSG_DONE) {
                CURL *curl = msg->easy_handle;
                http_request *request;
                curl_easy_getinfo(curl, CURLINFO_PRIVATE, &request);

                long response_code_long;
                curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code_long);
                int response_code = (int)response_code_long;

                int rc = zsock_send (pipe, "icp", response_code, request->data, request->userp);
                assert (rc == 0);

                curl_multi_remove_handle (multi, curl);

                //  Remove curl from the pending handles and delete it
                void *handle = zlistx_find (pending_handles, curl);
                assert (handle);
                rc = zlistx_delete (pending_handles, handle);
                assert (rc == 0);
            }

            msg = curl_multi_info_read(multi, &msgq);
        }
    }

    zlistx_destroy (&pending_handles);
    curl_share_cleanup (share);
    curl_multi_cleanup (multi);
    curl_global_cleanup ();
}
Exemple #12
0
int
zloop_start (zloop_t *self)
{
    assert (self);
    int rc = 0;

    //  Main reactor loop
    while (!zsys_interrupted) {
        if (self->need_rebuild) {
            //  If s_rebuild_pollset() fails, break out of the loop and
            //  return its error
            rc = s_rebuild_pollset (self);
            if (rc)
                break;
        }
        rc = zmq_poll (self->pollset, (int) self->poll_size, s_tickless (self));
        if (rc == -1 || zsys_interrupted) {
            if (self->verbose)
                zsys_debug ("zloop: interrupted");
            rc = 0;
            break;              //  Context has been shut down
        }
        
        //  Handle any timers that have now expired
        int64_t time_now = zclock_mono ();
        s_timer_t *timer = (s_timer_t *) zlistx_first (self->timers);
        while (timer) {
            if (time_now >= timer->when) {
                if (self->verbose)
                    zsys_debug ("zloop: call timer handler id=%d", timer->timer_id);
                rc = timer->handler (self, timer->timer_id, timer->arg);
                if (rc == -1)
                    break;      //  Timer handler signaled break
                if (timer->times && --timer->times == 0)
                    zlistx_delete (self->timers, timer->list_handle);
                else
                    timer->when += timer->delay;
            }
            timer = (s_timer_t *) zlistx_next (self->timers);
        }
        
        //  Handle any tickets that have now expired
        s_ticket_t *ticket = (s_ticket_t *) zlistx_first (self->tickets);
        while (ticket && time_now >= ticket->when) {
            if (self->verbose)
                zsys_debug ("zloop: call ticket handler");
            rc = ticket->handler (self, 0, ticket->arg);
            if (rc == -1)
                break;      //  Timer handler signaled break
            zlistx_delete (self->tickets, ticket->list_handle);
            ticket = (s_ticket_t *) zlistx_next (self->tickets);
        }
        
        //  Handle any readers and pollers that are ready
        size_t item_nbr;
        for (item_nbr = 0; item_nbr < self->poll_size && rc >= 0; item_nbr++) {
            s_reader_t *reader = &self->readact [item_nbr];
            if (reader->handler) {
                if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
                && !reader->tolerant) {
                    if (self->verbose)
                        zsys_warning ("zloop: can't read %s socket: %s",
                                      zsock_type_str (reader->sock),
                                      zmq_strerror (zmq_errno ()));
                    //  Give handler one chance to handle error, then kill
                    //  reader because it'll disrupt the reactor otherwise.
                    if (reader->errors++) {
                        zloop_reader_end (self, reader->sock);
                        self->pollset [item_nbr].revents = 0;
                    }
                }
                else
                    reader->errors = 0;     //  A non-error happened

                if (self->pollset [item_nbr].revents) {
                    if (self->verbose)
                        zsys_debug ("zloop: call %s socket handler",
                                    zsock_type_str (reader->sock));
                    rc = reader->handler (self, reader->sock, reader->arg);
                    if (rc == -1 || self->need_rebuild)
                        break;
                }
            }
            else {
                s_poller_t *poller = &self->pollact [item_nbr];
                assert (self->pollset [item_nbr].socket == poller->item.socket);

                if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
                && !poller->tolerant) {
                    if (self->verbose)
                        zsys_warning ("zloop: can't poll %s socket (%p, %d): %s",
                                      poller->item.socket ?
                                      zsys_sockname (zsock_type (poller->item.socket)) : "FD",
                                      poller->item.socket, poller->item.fd,
                                      zmq_strerror (zmq_errno ()));
                    //  Give handler one chance to handle error, then kill
                    //  poller because it'll disrupt the reactor otherwise.
                    if (poller->errors++) {
                        zloop_poller_end (self, &poller->item);
                        self->pollset [item_nbr].revents = 0;
                    }
                }
                else
                    poller->errors = 0;     //  A non-error happened

                if (self->pollset [item_nbr].revents) {
                    if (self->verbose)
                        zsys_debug ("zloop: call %s socket handler (%p, %d)",
                                    poller->item.socket ?
                                    zsys_sockname (zsock_type (poller->item.socket)) : "FD",
                                    poller->item.socket, poller->item.fd);
                    rc = poller->handler (self, &self->pollset [item_nbr], poller->arg);
                    if (rc == -1 || self->need_rebuild)
                        break;
                }
            }
        }
        //  Now handle any timer zombies
        //  This is going to be slow if we have many timers; we might use
        //  a faster lookup on the timer list.
        while (zlistx_first (self->zombies)) {
            //  Get timer_id back from pointer
            int timer_id = (byte *) zlistx_detach (self->zombies, NULL) - (byte *) NULL;
            s_timer_remove (self, timer_id);
        }
        if (rc == -1)
            break;
    }
    self->terminated = true;
    return rc;
}
Exemple #13
0
void
zlistx_test (bool verbose)
{
    printf (" * zlistx: ");

    //  @selftest
    zlistx_t *list = zlistx_new ();
    assert (list);
    assert (zlistx_size (list) == 0);

    //  Test operations on an empty list
    assert (zlistx_first (list) == NULL);
    assert (zlistx_last (list) == NULL);
    assert (zlistx_next (list) == NULL);
    assert (zlistx_prev (list) == NULL);
    assert (zlistx_find (list, "hello") == NULL);
    assert (zlistx_delete (list, NULL) == -1);
    assert (zlistx_detach (list, NULL) == NULL);
    assert (zlistx_delete (list, NULL) == -1);
    assert (zlistx_detach (list, NULL) == NULL);
    zlistx_purge (list);
    zlistx_sort (list);

    //  Use item handlers
    zlistx_set_destructor (list, (zlistx_destructor_fn *) zstr_free);
    zlistx_set_duplicator (list, (zlistx_duplicator_fn *) strdup);
    zlistx_set_comparator (list, (zlistx_comparator_fn *) strcmp);

    //  Try simple insert/sort/delete/next
    assert (zlistx_next (list) == NULL);
    zlistx_add_end (list, "world");
    assert (streq ((char *) zlistx_next (list), "world"));
    zlistx_add_end (list, "hello");
    assert (streq ((char *) zlistx_prev (list), "hello"));
    zlistx_sort (list);
    assert (zlistx_size (list) == 2);
    void *handle = zlistx_find (list, "hello");
    char *item1 = (char *) zlistx_item (list);
    char *item2 = (char *) zlistx_handle_item (handle);
    assert (item1 == item2);
    assert (streq (item1, "hello"));
    zlistx_delete (list, handle);
    assert (zlistx_size (list) == 1);
    char *string = (char *) zlistx_detach (list, NULL);
    assert (streq (string, "world"));
    free (string);
    assert (zlistx_size (list) == 0);

    //  Check next/back work
    //  Now populate the list with items
    zlistx_add_start (list, "five");
    zlistx_add_end   (list, "six");
    zlistx_add_start (list, "four");
    zlistx_add_end   (list, "seven");
    zlistx_add_start (list, "three");
    zlistx_add_end   (list, "eight");
    zlistx_add_start (list, "two");
    zlistx_add_end   (list, "nine");
    zlistx_add_start (list, "one");
    zlistx_add_end   (list, "ten");

    //  Test our navigation skills
    assert (zlistx_size (list) == 10);
    assert (streq ((char *) zlistx_last (list), "ten"));
    assert (streq ((char *) zlistx_prev (list), "nine"));
    assert (streq ((char *) zlistx_prev (list), "eight"));
    assert (streq ((char *) zlistx_prev (list), "seven"));
    assert (streq ((char *) zlistx_prev (list), "six"));
    assert (streq ((char *) zlistx_prev (list), "five"));
    assert (streq ((char *) zlistx_first (list), "one"));
    assert (streq ((char *) zlistx_next (list), "two"));
    assert (streq ((char *) zlistx_next (list), "three"));
    assert (streq ((char *) zlistx_next (list), "four"));

    //  Sort by alphabetical order
    zlistx_sort (list);
    assert (streq ((char *) zlistx_first (list), "eight"));
    assert (streq ((char *) zlistx_last (list), "two"));

    //  Moving items around
    handle = zlistx_find (list, "six");
    zlistx_move_start (list, handle);
    assert (streq ((char *) zlistx_first (list), "six"));
    zlistx_move_end (list, handle);
    assert (streq ((char *) zlistx_last (list), "six"));
    zlistx_sort (list);
    assert (streq ((char *) zlistx_last (list), "two"));

    //  Copying a list
    zlistx_t *copy = zlistx_dup (list);
    assert (copy);
    assert (zlistx_size (copy) == 10);
    assert (streq ((char *) zlistx_first (copy), "eight"));
    assert (streq ((char *) zlistx_last (copy), "two"));
    zlistx_destroy (&copy);

    //  Delete items while iterating
    string = (char *) zlistx_first (list);
    assert (streq (string, "eight"));
    string = (char *) zlistx_next (list);
    assert (streq (string, "five"));
    zlistx_delete (list, zlistx_cursor (list));
    string = (char *) zlistx_next (list);
    assert (streq (string, "four"));

    zlistx_purge (list);
    zlistx_destroy (&list);
    //  @end

    printf ("OK\n");
}
Exemple #14
0
///
//  Delete an item, using its handle. Calls the item destructor is any is 
//  set. If handle is null, deletes the first item on the list. Returns 0 
//  if an item was deleted, -1 if not. If cursor was at item, moves cursor
//  to previous item, so you can delete items while iterating forwards    
//  through a list.                                                       
int QZlistx::deleteNoConflict (void *handle)
{
    int rv = zlistx_delete (self, handle);
    return rv;
}