Receiving from message queues - c

I have successfully created the message queue by using the following command:
msgIdHareTurtle = msgget(keyHareTurtle, 0644 | IPC_CREAT | O_NONBLOCK);
Now I want to send the queue to some other process I used,
msgsnd(msgIdHareTurtle, (struct msgbuf *)&bufHareTurtle, sizeof(int), IPC_NOWAIT);
and I try to receive it in different process by:
msgrcv(msgIdHareTurtle, (struct msgbuf *)&bufHareTurtle, sizeof(int), 0, IPC_NOWAIT);
my structure bufHareTurtle is of following type:
typedef struct smsgbuf{
long mtype;
unsigned int position;
} smsgbuf;
My question: The sending was successful and the program(both the processes) is running too but whenever I am sending an unsigned integer for example 2 , I AM ALWAYS GETTING THE RECEIVED VALUE (IN LATTER PROCESS) AS 0 EVRYTIME. Could somebody tell me what is the error in this code or what could be possible error elsewhere.

The problem was there in synchronization. The sending to the queue was delayed due to sleep inserted in between. I corrected it and the error was gone

Related

mq_receive returns "Message too long" even though msg_len is greater than mq_msgsize

I am trying to understand the working of message queues in Linux.
Eventually, I'd want to have a program where I could send and receive stuff between different threads/processes, but to start off, I only create a message queue, and have it block on an input in a queue, but mq_receive() returns Message too long.
Looking at the documentation, this error indicates `msg_len was less than the mq_msgsize attribute of the message queue., but this isn't the case for me.
Sorry if I'm missing something obvious but I couldn't figure it out.
#define MAX_MESSAGES 10
#define MAX_MSG_SIZE 256
#define MSG_BUFFER_SIZE MAX_MSG_SIZE + 10
int main()
{
mqd_t qd_server, qd_client;
char in_buffer [MSG_BUFFER_SIZE];
char out_buffer [MSG_BUFFER_SIZE];
struct mq_attr attr, tmpAttr;
attr.mq_flags = 0;
attr.mq_maxmsg = MAX_MESSAGES;
attr.mq_msgsize = MAX_MSG_SIZE;
attr.mq_curmsgs = 0;
if ((qd_server = mq_open ("/sp-example-server", O_RDONLY|O_CREAT, 0644, &attr)) == -1)
{
printf("%s\n", strerror(errno));
}
if (mq_getattr(qd_server, &tmpAttr) == -1)
{
printf("mq_getattr error");
}
printf("Maximum # of messages on queue: %ld\n", tmpAttr.mq_maxmsg);
printf("Maximum message size: %ld\n", tmpAttr.mq_msgsize);
int iret = mq_receive(qd_server, in_buffer, sizeof(in_buffer), NULL);
if (iret == -1)
{
printf("%s\n", strerror(errno));
}
return 0;
}
Edit:
After running mmq_getattr(qd_server, & tmpAttr), it seems as if attributes were never set which probably is the cause. Now on to why are attributes not set?
// output:
Maximum # of messages on queue: 10
Maximum message size: 8192
The code you've shown us did not create the /sp-example-server message queue.
Instead, some prior process created that queue with the values you see for mq_maxmsg and mq_msgsize. If the queue's creator omitted the attribute specification — that is, passed a NULL struct mq_attr * to mq_open — then the implementation will provide default values. On Linux, these defaults match the values you see.
It seems plausible some early version of your code called mq_open with NULL attributes, and thus O_CREAT'd the queue as you are experiencing it now.
To accommodate this, you might reboot or mq_unlink the queue, forcing the next call to mq_open to re-create it. More defensively, when you do not open the queue O_EXCLusively, then use mq_getattr to validate the queue's attributes.

C binary message over amqp

Currently I have a daemon listening for TCP/UDP packets on port X using the recvfrom system call:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
and then the data is send over a message queue with the msgsnd system call:
int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
I would like to replace the msgsnd system call with RabbitMQ and send the messages using amqp protocol. The problem I am facing is the format of the data received and send over the RabbitMQ. When I receive data on port then I try to send it like this:
ssize_t recvfrom(
sockfd, msgbufInst.msgContent, len, flags, src_addr, addrlen
);
send_over_rabbitmq(msgbufInst.msgContent);
where send_over_rabbitmq is pretty much
send_over_rabbitmq(char *rawData){
amqp_bytes_t payload;
payload.len = sizeof(rawData);
payload.bytes = rawData;
int result = amqp_basic_publish((*channel)->conn, 1,
amqp_cstring_bytes("myExchange"),
amqp_cstring_bytes(""), 0, 0, NULL, payload);
}
The payload is send and received successfully but some data is lose. When I consume the message from the queue the payload is not the same as when I used the system call to send/consume messages. I am sure that it has to do with the data types that I am using but can't figure it out yet.
As I noted in a comment:
In the send_over_rabbitmq() function, the value of sizeof(rawData) is probably 8, and maybe only 4 — it's the size of the pointer variable, and not the length of the data that it points at. That probably isn't what you want.
You'll need to send more information to the send_over_rabbitmq() function — most noticeably, the length of the data received from recvfrom(). That means capturing the information — you should be checking the return value from recvfrom() anyway before trying to relay information via RabbitMQ.

Msgsnd in c: permission denied

I am trying to create a message queue and then send a message to it. Here is what I have tried:
int main(){
int myMsgQueue;
struct msgStruct{
long mtype;
char mtext[LENGTH];
};
struct msgStruct myMsg;
myMsg.mtype = (long)getpid();
strcpy(myMsg.mtext,"Hey there"); //Setting the string of the message
if((myMsgQueue = msgget(IPC_PRIVATE,IPC_CREAT | IPC_EXCL)) == -1) //Creating the message queue
errore(__LINE__);
if(msgsnd(myMsgQueue,&myMsg,sizeof(myMsg) - sizeof(long),0) == -1) //Sending the message
errore(__LINE__);
if(msgctl(myMsgQueue,IPC_RMID,0) == -1) //Deleting the message queue
errore(__LINE__);
}
The function errore simply prints out a string which explains the error using strerror(errno).
However, the code does not seem to work: errore prints "Permission denied" as msgsnd returns -1.
I cannot figure out what is the problem: I am initializing the message queue and an adequate message structure, then creating a message of a type corresponding to the process' pid and of a text corresponding to "Hey there", then sending the message.
What am I missing?
Read the man page man page
A message queue identifier exists for the argument key, but operation
permission as specified by the low-order 9 bits of msgflg would not be
granted;

impact of incorrect message size in old unix message queues routines

I'm reverse engineering a program that uses Unix Message queues (the old ones, not Posix) and I saw that the size provided to msgsnd or msgrcv is not correct, it is bigger than what it should be. Example :
struct requestmir {
long type;
char name[128];
int timeout;
long test;
};
int sizereqmir=sizeof(struct requestmir);
"sizereqmir" is used in msgsnd but according to some websites, the size of "type" (sizeof(long)) must be substracted from "sizereqmir".
If we use a bigger size (without substracting the size of the type), can a buffer overflow occur (with no consequences) ? because the program is running properly but I need to know if I have to correct the sizes.
And for msgrcv, does the size indicate the maximum size to read ? if 2 small messages are sent to a message queue and I want to read only one message but I provide a big size, will I found the 2 messages in my buffer whereas I want only one message ? Example :
// in processes that send msg logs...
// shared struct
struct log{
long type;
char text[512];
};
struct log mess;
mess.type= 15;
//... put some text in log.text
if(msgsnd(msgqId,&mess,strlen(mess.text)+1, IPC_NOWAIT);
//....
// EOF #####
//*** in the process that read log msg from the message queue and write them to a file
struct log mess;
msgrcv(msgqId,&mess,512,0,0); //512 max text size
In the last msgrcv, I try to read 512 bytes max from the queue, if 2 different processes send short log messages, they will be found in "mess", it that correct ?

linux rpc order and retransmision

We use RPC (udp socket) in our application and we noticed that RPC retransmit it messages when it was not received (or confirmed) by the target application.
Does RPC present the order of messages? let say we have message 1 and message 2, does it wait for message 1 to be confirmed by the receiver and then sends message 2?
also I wasn't been able to find how many retries it does by default and if the sending failed after x retries does it log it somewhere so we can inspect it?
Thanks
RPC library has a call to control how long to wait before retry the request:
struct timeval tv;
clnt_control(cl, CLSET_TIMEOUT, (char *) &tv);
when you invoke an rpc call, you provide total timeout:
enum clnt_stat clnt_call(CLIENT *clnt, unsigned long procnum,
xdrproc_t inproc, char *in,
xdrproc_t outproc, char *out,
struct timeval tout);
if you divide tout by value you set with clnt_control, you will get number of retries.
The sync/async behavior depends on your application only.

Resources