Fawkes API Fawkes Development Version
msg.cpp
1
2/***************************************************************************
3 * msg.cpp - IPC message queue
4 *
5 * Generated: Mon Mar 13 17:44:59 2006
6 * Copyright 2005-2006 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <sys/ipc.h>
25#include <sys/msg.h>
26#include <sys/types.h>
27#include <utils/ipc/msg.h>
28#include <utils/ipc/msg_exceptions.h>
29
30#include <errno.h>
31
32namespace fawkes {
33
34/// @cond INTERNALS
35class IPCMessageQueueData
36{
37public:
38 key_t key;
39 int msgqid;
40 int msgflg;
41};
42/// @endcond
43
44/** @class IPCMessageQueue utils/ipc/msg.h
45 * IPC message queue.
46 * This class gives access to IPC message queues. You can use this to send
47 * messages between different applications running on the same host.
48 *
49 * @see qa_ipc_msg.cpp
50 * @ingroup IPC
51 * @author Tim Niemueller
52 *
53 *
54 * @var IPCMessageQueue::destroy_on_delete
55 * destroy this message queue on delete?
56 *
57 */
58
59/** Maximum size of a message.
60 */
61const int IPCMessageQueue::MaxMessageSize = 8192; // from linux/msg.h
62
63/** Create or open a message queue
64 * If a message key with the given identification criteria exists it is
65 * opened for sending and receiving. If no such queue exists a new one is
66 * create. Use isValid() to check success.
67 * @param path path given to ftok to create the message queue identifier
68 * @param id id given to ftok to create the message queue identifier
69 * @param destroy_on_delete destroy the message queue if the dtor is called?
70 * @param create Create the queue if it does not exist, do not create the queue
71 * otherwise, use isValid() to check if queue was opened
72 */
73IPCMessageQueue::IPCMessageQueue(const char *path, char id, bool create, bool destroy_on_delete)
74{
75 data = new IPCMessageQueueData();
76
77 this->destroy_on_delete = destroy_on_delete;
78
79 data->msgflg = 0666;
80 if (create) {
81 data->msgflg |= IPC_CREAT;
82 }
83
84 data->key = ftok(path, id);
85 data->msgqid = msgget(data->key, data->msgflg);
86}
87
88/** Create or open a message queue
89 * This is a simplified version of the above function. The path is omitted
90 * and . (dot, the current working directory) is used instead.
91 * @param id id give to ftok to create the message queue identifier, preferably
92 * use an id from msg_registry.h
93 * @param destroy_on_delete set to true to destroy the message queue if the dtor is called
94 * @param create if true create the queue if it does not exist, do not create the queue
95 * otherwise, use isValid() to check if queue was opened successfully.
96 */
97IPCMessageQueue::IPCMessageQueue(int id, bool create, bool destroy_on_delete)
98{
99 data = new IPCMessageQueueData();
100
101 this->destroy_on_delete = destroy_on_delete;
102
103 data->msgflg = 0666;
104 if (create) {
105 data->msgflg |= IPC_CREAT;
106 }
107
108 data->key = id;
109 data->msgqid = msgget(data->key, data->msgflg);
110}
111
112/** Destructor */
114{
115 if ((data->msgqid != -1) && destroy_on_delete) {
116 msgctl(data->msgqid, IPC_RMID, 0);
117 }
118 delete data;
119}
120
121/** Check if the message queue is valid
122 * If the queue could not be opened yet (for example if you gave create=false to the
123 * constructor) isValid() will try to open the queue.
124 * @return This method returns false if the message queue could not be opened
125 * or if it has been closed, it returns true if messages can be sent or received.
126 */
127bool
129{
130 if (data->msgqid == -1) {
131 data->msgqid = msgget(data->key, data->msgflg);
132 if (data->msgqid == -1) {
133 return false;
134 } else {
135 struct msqid_ds m;
136 if (msgctl(data->msgqid, IPC_STAT, &m) != -1) {
137 return true;
138 } else {
139 data->msgqid = -1;
140 return false;
141 }
142 }
143 } else {
144 struct msqid_ds m;
145 if (msgctl(data->msgqid, IPC_STAT, &m) != -1) {
146 return true;
147 } else {
148 data->msgqid = -1;
149 return false;
150 }
151 }
152}
153
154/** Receive messages from this queue of the given message type
155 * @param mtype the message type
156 * @param msg The place where the received data will be copied on success.
157 * You _must_ have the mtype long field as described for MessageStruct. On recv the
158 * struct does not have to be inialized,
159 * but the memory has to be allocated already. See the note about the data_size!
160 * @param data_size The size of the _whole_ struct, including the mtype field. NOT
161 * just the size of the mtext field as for msgrcv!
162 * @return returns true, if a message of the appropriate type could be read that fitted
163 * the given memory size. The received data is stored in data.
164 * @see MessageStruct
165 * @exception MessageTooBigException Message was too big and did not fit into buffer.
166 * Message remains on queue and needs to be fetched
167 * with a bigger buffer.
168 */
169bool
170IPCMessageQueue::recv(long mtype, MessageStruct *msg, unsigned int data_size)
171{
172 if (data->msgqid == -1)
173 return false;
174
175 if (msgrcv(data->msgqid, (struct msgbuf *)msg, data_size - sizeof(long), mtype, IPC_NOWAIT)
176 == -1) {
177 if ((errno == EIDRM) || (errno == EINVAL)) {
178 data->msgqid = -1;
179 }
180 if (errno == E2BIG) {
182 }
183 return false;
184 } else {
185 return true;
186 }
187}
188
189/** Receive messages from this queue of any type
190 * @param msg a pointer to a message struct of the appropriate size. This is
191 * most likely your own incarnation. It must point to a chunk of memory
192 * which has at least max_data_size bytes.
193 * @param max_data_size The maximum size the data may have.
194 * @param data_size after successfuly recv will contain the number of bytes actually
195 * copied into data including the size of the mtype field!
196 * @return true, if a message could be read that fitted
197 * the given memory size. The received data is stored in data. False, if
198 * no message was in the queue or the queue has been removed.
199 * @see MessageStruct
200 */
201bool
202IPCMessageQueue::recvNext(MessageStruct *msg, unsigned int max_data_size, int *data_size)
203{
204 if (data->msgqid == -1)
205 return false;
206
207 if ((*data_size =
208 msgrcv(data->msgqid, (struct msgbuf *)msg, max_data_size - sizeof(long), 0, IPC_NOWAIT))
209 == -1) {
210 if ((errno == EIDRM) || (errno == EINVAL)) {
211 data->msgqid = -1;
212 }
213 return false;
214 } else {
215 return true;
216 }
217}
218
219/** Receive messages from this queue of the given message type
220 * @param msg The data to be sent, see note for recv()
221 * @param data_size the full data size (sizeof(typeof(data))), NOT just the size of the
222 * mtext field (see recv()).
223 * @return true, if the message could be sent, false otherwise.
224 * @see MessageStruct
225 */
226bool
227IPCMessageQueue::send(MessageStruct *msg, unsigned int data_size)
228{
229 if (data->msgqid == -1)
230 return false;
231
232 if (msgsnd(data->msgqid, msg, data_size - sizeof(long), IPC_NOWAIT) == -1) {
233 if (errno == EIDRM) {
234 data->msgqid = -1;
235 }
236 return false;
237 } else {
238 return true;
239 }
240}
241
242} // end namespace fawkes
bool recvNext(MessageStruct *msg, unsigned int max_data_size, int *data_size)
Receive messages from this queue of any type.
Definition: msg.cpp:202
~IPCMessageQueue()
Destructor.
Definition: msg.cpp:113
bool recv(long mtype, MessageStruct *msg, unsigned int data_size)
Receive messages from this queue of the given message type.
Definition: msg.cpp:170
static const int MaxMessageSize
Maximum size of a message.
Definition: msg.h:34
bool isValid()
Check if the message queue is valid If the queue could not be opened yet (for example if you gave cre...
Definition: msg.cpp:128
static long mtype(char *buffer)
Get the message type.
Definition: msg.h:63
bool destroy_on_delete
destroy this message queue on delete?
Definition: msg.h:69
bool send(MessageStruct *msg, unsigned int data_size)
Receive messages from this queue of the given message type.
Definition: msg.cpp:227
IPCMessageQueue(const char *path, char id, bool create=false, bool destroy_on_delete=false)
Create or open a message queue If a message key with the given identification criteria exists it is o...
Definition: msg.cpp:73
Message did not fit into buffer.
Fawkes library namespace.
This is the struct of the messages that has to be fed to send and receive methods.
Definition: msg.h:40