0
@@ -21,10 +21,18 @@ using namespace std;
0
* This class provides convenience methods for:
0
- * - sending and receiving discrete messages over a file descriptor.
0
- * A message is just a list of strings.
0
+ * - sending and receiving messages over a file descriptor.
0
* - file descriptor passing over a Unix socket.
0
+ * There are two kinds of messages:
0
+ * - Array messages. These are just a list of strings, and the message
0
+ * itself has a specific length. The contained strings may not
0
+ * contain NUL characters ('\0').
0
+ * - Scalar messages. These are byte strings which may contain arbitrary
0
+ * binary data. Scalar messages also have a specific length.
0
+ * The protocol is designed to be low overhead, easy to implement and
0
* MessageChannel is to be wrapped around a file descriptor. For example:
0
@@ -32,9 +40,14 @@ using namespace std;
0
* MessageChannel channel1(p[0]);
0
* MessageChannel channel2(p[1]);
0
+ * // Send an array message.
0
* channel2.write("hello", "world !!", NULL);
0
- * channel1.read(args); // args now contains { "hello", "world !!" }
0
+ * channel1.read(args); // args now contains { "hello", "world !!" }
0
+ * // Send a scalar message.
0
+ * channel2.writeScalar("some long string which can contain arbitrary binary data");
0
+ * string str = channel1.readScalar();
0
* The life time of a MessageChannel is independent from that of the
0
@@ -43,12 +56,14 @@ using namespace std;
0
* if you want to close the file descriptor.
0
* @note I/O operations are not buffered.
0
- * @note Be careful with mixing the sending/receiving of messages file
0
- * descriptor passing. These operations have stream properties.
0
- * Suppose you first send a message, then pass a file descriptor.
0
- * If the other side of the communication channel first tries to
0
- * receive a file descriptor, and then tries to receive a message,
0
- * then bad things will happen.
0
+ * @note Be careful with mixing the sending/receiving of array messages,
0
+ * scalar messages and file descriptors. If you send a collection of any
0
+ * of these in a specific order, then the receiving side must receive them
0
+ * in the exact some order. So suppose you first send a message, then a
0
+ * file descriptor, then a scalar, then the receiving side must first
0
+ * receive a message, then a file descriptor, then a scalar. If the
0
+ * receiving side does things in the wrong order then bad things will
0
* @note MessageChannel is thread-safe.
0
@@ -56,6 +71,25 @@ private:
0
const static char DELIMITER = '\0';
0
+ void writeLength(unsigned short len) {
0
+ ret = ::write(fd, (char *) &l + written, sizeof(l) - written);
0
+ } while (ret == -1 && errno == EINTR);
0
+ throw SystemException("write() failed", errno);
0
+ } while (written < sizeof(l));
0
* Construct a new MessageChannel with no underlying file descriptor.
0
@@ -86,7 +120,7 @@ public:
0
- * Send
the message, which consists of the given elements, over the underlying
0
+ * Send
an array message, which consists of the given elements, over the underlying
0
* @throws SystemException An error occured while writing the data to the file descriptor.
0
@@ -123,7 +157,7 @@ public:
0
- * Send
the message, which consists of the given strings, over the underlying
0
+ * Send
an array message, which consists of the given strings, over the underlying
0
* @param name The first element of the message to send.
0
@@ -149,6 +183,27 @@ public:
0
+ void writeScalar(const string &str) {
0
+ writeScalar(str.c_str(), str.size());
0
+ void writeScalar(const char *data, unsigned short size) {
0
+ unsigned int written = 0;
0
+ ret = ::write(fd, data + written, size - written);
0
+ } while (ret == -1 && errno == EINTR);
0
+ throw SystemException("write() failed", errno);
0
+ } while (written < size);
0
* Pass a file descriptor. This only works if the underlying file
0
* descriptor is a Unix socket.
Comments
No one has commented yet.