Esempio n. 1
0
int
zloop_poller (zloop_t *self, zmq_pollitem_t *item, zloop_fn handler, void *arg)
{
    assert (self);

    if (item->socket
    &&  streq (zsys_sockname (zsock_type (item->socket)), "UNKNOWN"))
        return -1;

    s_poller_t *poller = s_poller_new (item, handler, arg);
    if (poller) {
        poller->list_handle = zlistx_add_end (self->pollers, poller);
        if (!poller->list_handle) {
            s_poller_destroy (&poller);
            return -1;
        }
        self->need_rebuild = true;
        if (self->verbose)
            zsys_debug ("zloop: register %s poller (%p, %d)",
                        item->socket ? zsys_sockname (zsock_type (item->socket)) : "FD",
                        item->socket, item->fd);
        return 0;
    }
    else
        return -1;
}
Esempio n. 2
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);
}
Esempio n. 3
0
int
zmailer_msg_send (zmailer_msg_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZMAILER_MSG_MAIL:
            frame_size += 2;            //  version
            frame_size += 1 + strlen (self->from);
            frame_size += 4;
            if (self->to)
                frame_size += strlen (self->to);
            frame_size += 4;
            if (self->subject)
                frame_size += strlen (self->subject);
            frame_size += 4;
            if (self->request)
                frame_size += strlen (self->request);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 0);
    PUT_NUMBER1 (self->id);
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case ZMAILER_MSG_MAIL:
            PUT_NUMBER2 (1);
            PUT_STRING (self->from);
            if (self->to) {
                PUT_LONGSTR (self->to);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            if (self->subject) {
                PUT_LONGSTR (self->subject);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            if (self->request) {
                PUT_LONGSTR (self->request);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    return 0;
}
Esempio n. 4
0
int
zpubsub_filter_send (zpubsub_filter_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZPUBSUB_FILTER_FILTER:
            frame_size += 2;            //  magic
            frame_size += 2;            //  version
            frame_size += 1 + strlen (self->partition);
            frame_size += 1 + strlen (self->topic);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 7);
    PUT_NUMBER1 (self->id);
    size_t nbr_frames = 1;              //  Total number of frames to send
    
    switch (self->id) {
        case ZPUBSUB_FILTER_FILTER:
            PUT_NUMBER2 (ZPUBSUB_FILTER_MAGIC_NUMBER);
            PUT_NUMBER2 (ZPUBSUB_FILTER_VERSION);
            PUT_STRING (self->partition);
            PUT_STRING (self->topic);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);
    
    return 0;
}
Esempio n. 5
0
int
zpubsub_filter_recv (zpubsub_filter_t *self, zsock_t *input)
{
    assert (input);
    
    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("zpubsub_filter: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("zpubsub_filter: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);
    
    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 7)) {
        zsys_warning ("zpubsub_filter: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZPUBSUB_FILTER_FILTER:
            {
                uint16_t magic;
                GET_NUMBER2 (magic);
                if (magic != ZPUBSUB_FILTER_MAGIC_NUMBER) {
                    zsys_warning ("zpubsub_filter: magic is invalid");
                    goto malformed;
                }
            }
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != ZPUBSUB_FILTER_VERSION) {
                    zsys_warning ("zpubsub_filter: version is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->partition);
            GET_STRING (self->topic);
            break;

        default:
            zsys_warning ("zpubsub_filter: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("zpubsub_filter: zpubsub_filter malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Esempio n. 6
0
int
mdp_client_msg_recv (mdp_client_msg_t *self, zsock_t *input)
{
    assert (input);
    
    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("mdp_client_msg: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("mdp_client_msg: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);
    
    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 4)) {
        zsys_warning ("mdp_client_msg: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case MDP_CLIENT_MSG_CLIENT_REQUEST:
            {
                char version [256];
                GET_STRING (version);
                if (strneq (version, "MDPC02")) {
                    zsys_warning ("mdp_client_msg: version is invalid");
                    goto malformed;
                }
            }
            {
                byte messageid;
                GET_NUMBER1 (messageid);
                if (messageid != 1) {
                    zsys_warning ("mdp_client_msg: messageid is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->service);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->body);
            if (zsock_rcvmore (input))
                self->body = zmsg_recv (input);
            else
                self->body = zmsg_new ();
            break;

        case MDP_CLIENT_MSG_CLIENT_PARTIAL:
            {
                char version [256];
                GET_STRING (version);
                if (strneq (version, "MDPC02")) {
                    zsys_warning ("mdp_client_msg: version is invalid");
                    goto malformed;
                }
            }
            {
                byte messageid;
                GET_NUMBER1 (messageid);
                if (messageid != 2) {
                    zsys_warning ("mdp_client_msg: messageid is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->service);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->body);
            if (zsock_rcvmore (input))
                self->body = zmsg_recv (input);
            else
                self->body = zmsg_new ();
            break;

        case MDP_CLIENT_MSG_CLIENT_FINAL:
            {
                char version [256];
                GET_STRING (version);
                if (strneq (version, "MDPC02")) {
                    zsys_warning ("mdp_client_msg: version is invalid");
                    goto malformed;
                }
            }
            {
                byte messageid;
                GET_NUMBER1 (messageid);
                if (messageid != 3) {
                    zsys_warning ("mdp_client_msg: messageid is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->service);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->body);
            if (zsock_rcvmore (input))
                self->body = zmsg_recv (input);
            else
                self->body = zmsg_new ();
            break;

        default:
            zsys_warning ("mdp_client_msg: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("mdp_client_msg: mdp_client_msg malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Esempio n. 7
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;
}
Esempio n. 8
0
///
//  Get socket option `type`.
int QZsock::type ()
{
    int rv = zsock_type (self);
    return rv;
}
Esempio n. 9
0
int
zproto_example_send (zproto_example_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            frame_size += 2;            //  sequence
            frame_size += 2;            //  version
            frame_size += 1;            //  level
            frame_size += 1;            //  event
            frame_size += 2;            //  node
            frame_size += 2;            //  peer
            frame_size += 8;            //  time
            frame_size += 1 + strlen (self->host);
            frame_size += 4;
            if (self->data)
                frame_size += strlen (self->data);
            break;
        case ZPROTO_EXAMPLE_STRUCTURES:
            frame_size += 2;            //  sequence
            frame_size += 4;            //  Size is 4 octets
            if (self->aliases) {
                char *aliases = (char *) zlist_first (self->aliases);
                while (aliases) {
                    frame_size += 4 + strlen (aliases);
                    aliases = (char *) zlist_next (self->aliases);
                }
            }
            frame_size += 4;            //  Size is 4 octets
            if (self->headers) {
                self->headers_bytes = 0;
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    self->headers_bytes += 1 + strlen (zhash_cursor (self->headers));
                    self->headers_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            frame_size += self->headers_bytes;
            break;
        case ZPROTO_EXAMPLE_BINARY:
            frame_size += 2;            //  sequence
            frame_size += 4;            //  flags
            frame_size += 4;            //  Size is 4 octets
            if (self->public_key)
                frame_size += zchunk_size (self->public_key);
            frame_size += ZUUID_LEN;    //  identifier
            break;
        case ZPROTO_EXAMPLE_TYPES:
            frame_size += 2;            //  sequence
            frame_size += 1 + strlen (self->client_forename);
            frame_size += 1 + strlen (self->client_surname);
            frame_size += 1 + strlen (self->client_mobile);
            frame_size += 1 + strlen (self->client_email);
            frame_size += 1 + strlen (self->supplier_forename);
            frame_size += 1 + strlen (self->supplier_surname);
            frame_size += 1 + strlen (self->supplier_mobile);
            frame_size += 1 + strlen (self->supplier_email);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 0);
    PUT_NUMBER1 (self->id);
    bool have_content = false;
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            PUT_NUMBER2 (self->sequence);
            PUT_NUMBER2 (3);
            PUT_NUMBER1 (self->level);
            PUT_NUMBER1 (self->event);
            PUT_NUMBER2 (self->node);
            PUT_NUMBER2 (self->peer);
            PUT_NUMBER8 (self->time);
            PUT_STRING (self->host);
            if (self->data) {
                PUT_LONGSTR (self->data);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            break;

        case ZPROTO_EXAMPLE_STRUCTURES:
            PUT_NUMBER2 (self->sequence);
            if (self->aliases) {
                PUT_NUMBER4 (zlist_size (self->aliases));
                char *aliases = (char *) zlist_first (self->aliases);
                while (aliases) {
                    PUT_LONGSTR (aliases);
                    aliases = (char *) zlist_next (self->aliases);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty string array
            if (self->headers) {
                PUT_NUMBER4 (zhash_size (self->headers));
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    PUT_STRING (zhash_cursor (self->headers));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            break;

        case ZPROTO_EXAMPLE_BINARY:
            PUT_NUMBER2 (self->sequence);
            PUT_OCTETS (self->flags, 4);
            if (self->public_key) {
                PUT_NUMBER4 (zchunk_size (self->public_key));
                memcpy (self->needle,
                        zchunk_data (self->public_key),
                        zchunk_size (self->public_key));
                self->needle += zchunk_size (self->public_key);
            }
            else
                PUT_NUMBER4 (0);    //  Empty chunk
            if (self->identifier)
                zuuid_export (self->identifier, self->needle);
            else
                memset (self->needle, 0, ZUUID_LEN);
            self->needle += ZUUID_LEN;
            nbr_frames++;
            nbr_frames += self->content? zmsg_size (self->content): 1;
            have_content = true;
            break;

        case ZPROTO_EXAMPLE_TYPES:
            PUT_NUMBER2 (self->sequence);
            PUT_STRING (self->client_forename);
            PUT_STRING (self->client_surname);
            PUT_STRING (self->client_mobile);
            PUT_STRING (self->client_email);
            PUT_STRING (self->supplier_forename);
            PUT_STRING (self->supplier_surname);
            PUT_STRING (self->supplier_mobile);
            PUT_STRING (self->supplier_email);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    //  Now send any frame fields, in order
    if (self->id == ZPROTO_EXAMPLE_BINARY) {
        //  If address isn't set, send an empty frame
        if (self->address)
            zframe_send (&self->address, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
        else
            zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0));
    }
    //  Now send the content if necessary
    if (have_content) {
        if (self->content) {
            zframe_t *frame = zmsg_first (self->content);
            while (frame) {
                zframe_send (&frame, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
                frame = zmsg_next (self->content);
            }
        }
        else
            zmq_send (zsock_resolve (output), NULL, 0, 0);
    }
    return 0;
}
Esempio n. 10
0
int
zproto_example_recv (zproto_example_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("zproto_example: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("zproto_example: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 0)) {
        zsys_warning ("zproto_example: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            GET_NUMBER2 (self->sequence);
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != 3) {
                    zsys_warning ("zproto_example: version is invalid");
                    goto malformed;
                }
            }
            GET_NUMBER1 (self->level);
            GET_NUMBER1 (self->event);
            GET_NUMBER2 (self->node);
            GET_NUMBER2 (self->peer);
            GET_NUMBER8 (self->time);
            GET_STRING (self->host);
            GET_LONGSTR (self->data);
            break;

        case ZPROTO_EXAMPLE_STRUCTURES:
            GET_NUMBER2 (self->sequence);
            {
                size_t list_size;
                GET_NUMBER4 (list_size);
                self->aliases = zlist_new ();
                zlist_autofree (self->aliases);
                while (list_size--) {
                    char *string = NULL;
                    GET_LONGSTR (string);
                    zlist_append (self->aliases, string);
                    free (string);
                }
            }
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->headers = zhash_new ();
                zhash_autofree (self->headers);
                while (hash_size--) {
                    char key [256];
                    char *value = NULL;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->headers, key, value);
                    free (value);
                }
            }
            break;

        case ZPROTO_EXAMPLE_BINARY:
            GET_NUMBER2 (self->sequence);
            GET_OCTETS (self->flags, 4);
            {
                size_t chunk_size;
                GET_NUMBER4 (chunk_size);
                if (self->needle + chunk_size > (self->ceiling)) {
                    zsys_warning ("zproto_example: public_key is missing data");
                    goto malformed;
                }
                zchunk_destroy (&self->public_key);
                self->public_key = zchunk_new (self->needle, chunk_size);
                self->needle += chunk_size;
            }
            if (self->needle + ZUUID_LEN > (self->ceiling)) {
                zsys_warning ("zproto_example: identifier is invalid");
                goto malformed;
            }
            zuuid_destroy (&self->identifier);
            self->identifier = zuuid_new_from (self->needle);
            self->needle += ZUUID_LEN;
            //  Get next frame off socket
            if (!zsock_rcvmore (input)) {
                zsys_warning ("zproto_example: address is missing");
                goto malformed;
            }
            zframe_destroy (&self->address);
            self->address = zframe_recv (input);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case ZPROTO_EXAMPLE_TYPES:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->client_forename);
            GET_STRING (self->client_surname);
            GET_STRING (self->client_mobile);
            GET_STRING (self->client_email);
            GET_STRING (self->supplier_forename);
            GET_STRING (self->supplier_surname);
            GET_STRING (self->supplier_mobile);
            GET_STRING (self->supplier_email);
            break;

        default:
            zsys_warning ("zproto_example: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("zproto_example: zproto_example malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Esempio n. 11
0
int
xrap_traffic_send (xrap_traffic_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case XRAP_TRAFFIC_CONNECTION_OPEN:
            frame_size += 1 + strlen ("MALAMUTE");
            frame_size += 2;            //  version
            frame_size += 1 + strlen (self->address);
            break;
        case XRAP_TRAFFIC_XRAP_SEND:
            frame_size += 4;            //  timeout
            break;
        case XRAP_TRAFFIC_XRAP_OFFER:
            frame_size += 1 + strlen (self->route);
            frame_size += 1 + strlen (self->method);
            break;
        case XRAP_TRAFFIC_XRAP_DELIVER:
            frame_size += ZUUID_LEN;    //  sender
            break;
        case XRAP_TRAFFIC_OK:
            frame_size += 2;            //  status_code
            frame_size += 1 + strlen (self->status_reason);
            break;
        case XRAP_TRAFFIC_FAIL:
            frame_size += 2;            //  status_code
            frame_size += 1 + strlen (self->status_reason);
            break;
        case XRAP_TRAFFIC_ERROR:
            frame_size += 2;            //  status_code
            frame_size += 1 + strlen (self->status_reason);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 9);
    PUT_NUMBER1 (self->id);
    bool have_content = false;
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case XRAP_TRAFFIC_CONNECTION_OPEN:
            PUT_STRING ("MALAMUTE");
            PUT_NUMBER2 (1);
            PUT_STRING (self->address);
            break;

        case XRAP_TRAFFIC_XRAP_SEND:
            PUT_NUMBER4 (self->timeout);
            nbr_frames += self->content? zmsg_size (self->content): 1;
            have_content = true;
            break;

        case XRAP_TRAFFIC_XRAP_OFFER:
            PUT_STRING (self->route);
            PUT_STRING (self->method);
            break;

        case XRAP_TRAFFIC_XRAP_DELIVER:
            if (self->sender)
                zuuid_export (self->sender, self->needle);
            else
                memset (self->needle, 0, ZUUID_LEN);
            self->needle += ZUUID_LEN;
            nbr_frames += self->content? zmsg_size (self->content): 1;
            have_content = true;
            break;

        case XRAP_TRAFFIC_OK:
            PUT_NUMBER2 (self->status_code);
            PUT_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_FAIL:
            PUT_NUMBER2 (self->status_code);
            PUT_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_ERROR:
            PUT_NUMBER2 (self->status_code);
            PUT_STRING (self->status_reason);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    //  Now send the content if necessary
    if (have_content) {
        if (self->content) {
            zframe_t *frame = zmsg_first (self->content);
            while (frame) {
                zframe_send (&frame, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
                frame = zmsg_next (self->content);
            }
        }
        else
            zmq_send (zsock_resolve (output), NULL, 0, 0);
    }
    return 0;
}
Esempio n. 12
0
int
zgossip_msg_send (zgossip_msg_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZGOSSIP_MSG_HELLO:
            frame_size += 1;            //  version
            break;
        case ZGOSSIP_MSG_PUBLISH:
            frame_size += 1;            //  version
            frame_size += 1 + strlen (self->key);
            frame_size += 4;
            if (self->value)
                frame_size += strlen (self->value);
            frame_size += 4;            //  ttl
            break;
        case ZGOSSIP_MSG_PING:
            frame_size += 1;            //  version
            break;
        case ZGOSSIP_MSG_PONG:
            frame_size += 1;            //  version
            break;
        case ZGOSSIP_MSG_INVALID:
            frame_size += 1;            //  version
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 0);
    PUT_NUMBER1 (self->id);
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case ZGOSSIP_MSG_HELLO:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_PUBLISH:
            PUT_NUMBER1 (1);
            PUT_STRING (self->key);
            if (self->value) {
                PUT_LONGSTR (self->value);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            PUT_NUMBER4 (self->ttl);
            break;

        case ZGOSSIP_MSG_PING:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_PONG:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_INVALID:
            PUT_NUMBER1 (1);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    return 0;
}
Esempio n. 13
0
int
zmailer_msg_recv (zmailer_msg_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("zmailer_msg: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("zmailer_msg: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 0)) {
        zsys_warning ("zmailer_msg: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZMAILER_MSG_MAIL:
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != 1) {
                    zsys_warning ("zmailer_msg: version is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->from);
            GET_LONGSTR (self->to);
            GET_LONGSTR (self->subject);
            GET_LONGSTR (self->request);
            break;

        default:
            zsys_warning ("zmailer_msg: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("zmailer_msg: zmailer_msg malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Esempio n. 14
0
JNIEXPORT jint JNICALL
Java_org_zeromq_czmq_Zsock__1_1type (JNIEnv *env, jclass c, jlong self)
{
    jint type_ = (jint) zsock_type ((zsock_t *) (intptr_t) self);
    return type_;
}
Esempio n. 15
0
int
fmq_msg_send (fmq_msg_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case FMQ_MSG_OHAI:
            frame_size += 1 + strlen ("FILEMQ");
            frame_size += 2;            //  version
            break;
        case FMQ_MSG_ICANHAZ:
            frame_size += 4;
            if (self->path)
                frame_size += strlen (self->path);
            frame_size += 4;            //  Size is 4 octets
            if (self->options) {
                self->options_bytes = 0;
                char *item = (char *) zhash_first (self->options);
                while (item) {
                    self->options_bytes += 1 + strlen (zhash_cursor (self->options));
                    self->options_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->options);
                }
            }
            frame_size += self->options_bytes;
            frame_size += 4;            //  Size is 4 octets
            if (self->cache) {
                self->cache_bytes = 0;
                char *item = (char *) zhash_first (self->cache);
                while (item) {
                    self->cache_bytes += 1 + strlen (zhash_cursor (self->cache));
                    self->cache_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->cache);
                }
            }
            frame_size += self->cache_bytes;
            break;
        case FMQ_MSG_NOM:
            frame_size += 8;            //  credit
            frame_size += 8;            //  sequence
            break;
        case FMQ_MSG_CHEEZBURGER:
            frame_size += 8;            //  sequence
            frame_size += 1;            //  operation
            frame_size += 4;
            if (self->filename)
                frame_size += strlen (self->filename);
            frame_size += 8;            //  offset
            frame_size += 1;            //  eof
            frame_size += 4;            //  Size is 4 octets
            if (self->headers) {
                self->headers_bytes = 0;
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    self->headers_bytes += 1 + strlen (zhash_cursor (self->headers));
                    self->headers_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            frame_size += self->headers_bytes;
            frame_size += 4;            //  Size is 4 octets
            if (self->chunk)
                frame_size += zchunk_size (self->chunk);
            break;
        case FMQ_MSG_SRSLY:
            frame_size += 1 + strlen (self->reason);
            break;
        case FMQ_MSG_RTFM:
            frame_size += 1 + strlen (self->reason);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 3);
    PUT_NUMBER1 (self->id);
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case FMQ_MSG_OHAI:
            PUT_STRING ("FILEMQ");
            PUT_NUMBER2 (FMQ_MSG_VERSION);
            break;

        case FMQ_MSG_ICANHAZ:
            if (self->path) {
                PUT_LONGSTR (self->path);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            if (self->options) {
                PUT_NUMBER4 (zhash_size (self->options));
                char *item = (char *) zhash_first (self->options);
                while (item) {
                    PUT_STRING (zhash_cursor (self->options));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->options);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            if (self->cache) {
                PUT_NUMBER4 (zhash_size (self->cache));
                char *item = (char *) zhash_first (self->cache);
                while (item) {
                    PUT_STRING (zhash_cursor (self->cache));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->cache);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            break;

        case FMQ_MSG_NOM:
            PUT_NUMBER8 (self->credit);
            PUT_NUMBER8 (self->sequence);
            break;

        case FMQ_MSG_CHEEZBURGER:
            PUT_NUMBER8 (self->sequence);
            PUT_NUMBER1 (self->operation);
            if (self->filename) {
                PUT_LONGSTR (self->filename);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            PUT_NUMBER8 (self->offset);
            PUT_NUMBER1 (self->eof);
            if (self->headers) {
                PUT_NUMBER4 (zhash_size (self->headers));
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    PUT_STRING (zhash_cursor (self->headers));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            if (self->chunk) {
                PUT_NUMBER4 (zchunk_size (self->chunk));
                memcpy (self->needle,
                        zchunk_data (self->chunk),
                        zchunk_size (self->chunk));
                self->needle += zchunk_size (self->chunk);
            }
            else
                PUT_NUMBER4 (0);    //  Empty chunk
            break;

        case FMQ_MSG_SRSLY:
            PUT_STRING (self->reason);
            break;

        case FMQ_MSG_RTFM:
            PUT_STRING (self->reason);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    return 0;
}
Esempio n. 16
0
int
fmq_msg_recv (fmq_msg_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("fmq_msg: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("fmq_msg: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 3)) {
        zsys_warning ("fmq_msg: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case FMQ_MSG_OHAI:
            {
                char protocol [256];
                GET_STRING (protocol);
                if (strneq (protocol, "FILEMQ")) {
                    zsys_warning ("fmq_msg: protocol is invalid");
                    goto malformed;
                }
            }
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != FMQ_MSG_VERSION) {
                    zsys_warning ("fmq_msg: version is invalid");
                    goto malformed;
                }
            }
            break;

        case FMQ_MSG_OHAI_OK:
            break;

        case FMQ_MSG_ICANHAZ:
            GET_LONGSTR (self->path);
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->options = zhash_new ();
                zhash_autofree (self->options);
                while (hash_size--) {
                    char key [256];
                    char *value = NULL;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->options, key, value);
                    free (value);
                }
            }
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->cache = zhash_new ();
                zhash_autofree (self->cache);
                while (hash_size--) {
                    char key [256];
                    char *value = NULL;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->cache, key, value);
                    free (value);
                }
            }
            break;

        case FMQ_MSG_ICANHAZ_OK:
            break;

        case FMQ_MSG_NOM:
            GET_NUMBER8 (self->credit);
            GET_NUMBER8 (self->sequence);
            break;

        case FMQ_MSG_CHEEZBURGER:
            GET_NUMBER8 (self->sequence);
            GET_NUMBER1 (self->operation);
            GET_LONGSTR (self->filename);
            GET_NUMBER8 (self->offset);
            GET_NUMBER1 (self->eof);
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->headers = zhash_new ();
                zhash_autofree (self->headers);
                while (hash_size--) {
                    char key [256];
                    char *value = NULL;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->headers, key, value);
                    free (value);
                }
            }
            {
                size_t chunk_size;
                GET_NUMBER4 (chunk_size);
                if (self->needle + chunk_size > (self->ceiling)) {
                    zsys_warning ("fmq_msg: chunk is missing data");
                    goto malformed;
                }
                zchunk_destroy (&self->chunk);
                self->chunk = zchunk_new (self->needle, chunk_size);
                self->needle += chunk_size;
            }
            break;

        case FMQ_MSG_HUGZ:
            break;

        case FMQ_MSG_HUGZ_OK:
            break;

        case FMQ_MSG_KTHXBAI:
            break;

        case FMQ_MSG_SRSLY:
            GET_STRING (self->reason);
            break;

        case FMQ_MSG_RTFM:
            GET_STRING (self->reason);
            break;

        default:
            zsys_warning ("fmq_msg: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("fmq_msg: fmq_msg malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Esempio n. 17
0
///
//  Get socket option `type`.
int QmlZsock::type () {
    return zsock_type (self);
};
Esempio n. 18
0
int
mdp_client_msg_send (mdp_client_msg_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case MDP_CLIENT_MSG_CLIENT_REQUEST:
            frame_size += 1 + strlen ("MDPC02");
            frame_size += 1;            //  messageid
            frame_size += 1 + strlen (self->service);
            break;
        case MDP_CLIENT_MSG_CLIENT_PARTIAL:
            frame_size += 1 + strlen ("MDPC02");
            frame_size += 1;            //  messageid
            frame_size += 1 + strlen (self->service);
            break;
        case MDP_CLIENT_MSG_CLIENT_FINAL:
            frame_size += 1 + strlen ("MDPC02");
            frame_size += 1;            //  messageid
            frame_size += 1 + strlen (self->service);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 4);
    PUT_NUMBER1 (self->id);
    bool send_body = false;
    size_t nbr_frames = 1;              //  Total number of frames to send
    
    switch (self->id) {
        case MDP_CLIENT_MSG_CLIENT_REQUEST:
            PUT_STRING ("MDPC02");
            PUT_NUMBER1 (1);
            PUT_STRING (self->service);
            nbr_frames += self->body? zmsg_size (self->body): 1;
            send_body = true;
            break;

        case MDP_CLIENT_MSG_CLIENT_PARTIAL:
            PUT_STRING ("MDPC02");
            PUT_NUMBER1 (2);
            PUT_STRING (self->service);
            nbr_frames += self->body? zmsg_size (self->body): 1;
            send_body = true;
            break;

        case MDP_CLIENT_MSG_CLIENT_FINAL:
            PUT_STRING ("MDPC02");
            PUT_NUMBER1 (3);
            PUT_STRING (self->service);
            nbr_frames += self->body? zmsg_size (self->body): 1;
            send_body = true;
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);
    
    //  Now send the body if necessary
    if (send_body) {
        if (self->body) {
            zframe_t *frame = zmsg_first (self->body);
            while (frame) {
                zframe_send (&frame, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
                frame = zmsg_next (self->body);
            }
        }
        else
            zmq_send (zsock_resolve (output), NULL, 0, 0);
    }
    return 0;
}
Esempio n. 19
0
int
xrap_traffic_recv (xrap_traffic_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("xrap_traffic: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("xrap_traffic: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 9)) {
        zsys_warning ("xrap_traffic: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case XRAP_TRAFFIC_CONNECTION_OPEN:
            {
                char protocol [256];
                GET_STRING (protocol);
                if (strneq (protocol, "MALAMUTE")) {
                    zsys_warning ("xrap_traffic: protocol is invalid");
                    goto malformed;
                }
            }
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != 1) {
                    zsys_warning ("xrap_traffic: version is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->address);
            break;

        case XRAP_TRAFFIC_CONNECTION_PING:
            break;

        case XRAP_TRAFFIC_CONNECTION_PONG:
            break;

        case XRAP_TRAFFIC_CONNECTION_CLOSE:
            break;

        case XRAP_TRAFFIC_XRAP_SEND:
            GET_NUMBER4 (self->timeout);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case XRAP_TRAFFIC_XRAP_OFFER:
            GET_STRING (self->route);
            GET_STRING (self->method);
            break;

        case XRAP_TRAFFIC_XRAP_DELIVER:
            if (self->needle + ZUUID_LEN > (self->ceiling)) {
                zsys_warning ("xrap_traffic: sender is invalid");
                goto malformed;
            }
            zuuid_destroy (&self->sender);
            self->sender = zuuid_new_from (self->needle);
            self->needle += ZUUID_LEN;
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case XRAP_TRAFFIC_OK:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_FAIL:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_ERROR:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        default:
            zsys_warning ("xrap_traffic: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("xrap_traffic: xrap_traffic malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}