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