psmq_timedreceive(3)

bofc manual pages

psmq_timedreceive(3)



 

NAME

psmq_receivepsmq_timedreceivepsmq_timedreceive_ms - receive single message over psmq.  

SYNOPSIS

#include <psmq.h>

int psmq_receive(struct psmq *psmq, struct psmq_msg *msg, unsigned *prio)
int psmq_timedreceive(struct psmq *psmq, struct psmq_msg *msg, unsigned *prio, struct timespec *tp)
int psmq_timedreceive_ms(struct psmq *psmq, struct psmq_msg *msg, unsigned *prio, size_t ms)
char * PSMQ_TOPIC(struct psmq_msg psmq)
void * PSMQ_PAYLOAD(struct psmq_msg psmq)  

DESCRIPTION

Receive single control message or message that client has subscribed to. Functions will block calling thread until message is received. Message will be stored in user provided memory pointed by msg.

Message is stored in struct psmq_msg which definition is:

    struct psmq_msg {
        struct ctrl {
            char  cmd;
            unsigned char data;
        } ctrl;
        unsigned short paylen;
        char data[PSMQ_MSG_MAX];
    }

ctrl.cmd defines type of received message. This can be one of:

PSMQ_CTRL_CMD_PUBLISH
Received message on previously subscribed topics.
PSMQ_CTRL_CMD_SUBSCRIBE
Subscribe confirmation has been received.
PSMQ_CTRL_CMD_UNSUBSCRIBE
Unsubscribe confirmation has been received.
PSMQ_CTRL_CMD_CLOSE
Broker closed connection with the client.
PSMQ_CTRL_CMD_IOCTL
Response from the broker for ioctl request.

ctrl.data is a response status of received message. Or simply return code of a previous request. 0 is set when request was a success or errno when error occured. For example, when psmq_subscribe(3) has been sent, broker will reply with ctrl.cmd set to PSMQ_CTRL_CMD_SUBSCRIBE and ctrl.data set to 0 when subscribe has been successful or, for example EBADMSG when topic was not correct.

data contains both topic and payload data. Topic and payload can be extracted by using PSMQ_TOPIC() and PSMQ_PAYLOAD() macros and passing struct psmq_msg as argument. PSMQ_TOPIC() will return valid c-string with topic, while PSMQ_PAYLOAD() will return pointer where payload starts. Accessing pointer returned by PSMQ_PAYLOAD() is only valid when paylen is bigger than 0, otherwise you risk getting SIGSEGV from OS.

When ctrl.data is PSMQ_CTRL_CMD_IOCTL then data will not contain topic but first byte will be ioctl request number and all of the following bytes are ioctl specific. In general all of reponses from ioctl will require custom parsing. Check psmq_ioctl(3) for all possible ioctls.

paylen Length of payload part in data.

psmq_timedreceive(3) works same way as psmq_receive(3) but will block only until timeout tp occurs. Timeout is absolute time since Epoch when timeout should occur. If this function is called when timeout already occured (tp happens to be behind current time) and message is not available in queue, function will return immediately.

psmq_timedreceive_ms(3) works same way as psmq_timedreceive(3) but accepts relative timeout in form of ms. If message is not received in ms time from the moment function is called, then the function will return. If ms is set to 0 and message is not on the queue, function will return immediately.  

RETURN VALUE

When message is received 0 is returned. On error -1 with appropriate errno set is returned.  

ERRORS

EINVAL
psmq or msg is NULL.
EBADF
Subscribe queue is invalid inside passed psmq object. It is possible that psmq has not yet been initialized, or psmq_cleanup(3) has been called on it earlier, or psmq_init(3) failed.
EINTR
The call was interrupted by a signal handler.

psmq_timedreceive(3) and psmq_timedreceive_ms(3) can also return:

ETIMEDOUT
The call timedout before a message could be transferred.
 

EXAMPLE

Example shows how to initialize, subscribe and receive data from psmq. Note: error checking has been ommited for clarity.

    #include <psmq.h>
    #include <stdio.h>

    int main(void)
    {
        struct psmq psmq;
        int rpm;
        int i;

        /* initialize psmq object that will create /sub mqueue for
         * receiving data, and will connect to broker of name /brok.
         * Max items in queue is set to 10 */
        psmq_init(&psmq, "/brok", "/sub", 10);

        /* subscribe to receive revolution per minute information */
        psmq_subscribe(&psmq, "/can/+/rpm");

        for (i = 0; i != 10; ++i) {
            /* now we are ready to receive data. In this example we
             * simply print received rpm */
            struct psmq_msg msg;
            psmq_receive(&psmq, &msg, NULL);
            memcpy(&rpm, PSMQ_PAYLOAD(msg), sizeof(rpm));
            printf("topic: %s; rpm %d\n", PSMQ_TOPIC(msg), rpm);
        }

        /* after work is finished, we need to deregister from broker to
         * make space in broker for another client */
        psmq_cleanup(&psmq);
        return 0;
    }
 

BUG REPORTING

Please, report all bugs to "Michał Łyszczek <michal.lyszczek@bofc.pl>"  

SEE ALSO

psmqd(1), psmq-pub(1), psmq-sub(1), psmq_cleanup(3), psmq_init(3), psmq_publish(3), psmq_receive(3), psmq_subscribe(3), psmq_timedreceive(3), psmq_timedreceive_ms(3), psmq_unsubscribe(3), psmq_building(7), psmq_overview(7).

bofc.pl

19 May 2021 (v9999)

psmq_timedreceive(3)