blob: de9c39848c5bf94dab353f1c83e24213083e0c8b [file] [log] [blame]
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001//
2// Copyright 2005 The Android Open Source Project
3//
4// High-level message stream that sits on top of a pair of Pipes. Useful
5// for inter-process communication, e.g. between "simulator" and "runtime".
6//
7// All messages are sent in packets:
8// +00 16-bit length (of everything that follows), little-endian
9// +02 8-bit message type
10// +03 (reserved, must be zero)
11// +04 message body
12//
13#ifndef _LIBS_UTILS_MESSAGE_STREAM_H
14#define _LIBS_UTILS_MESSAGE_STREAM_H
15
16#ifdef HAVE_ANDROID_OS
17#error DO NOT USE THIS FILE IN THE DEVICE BUILD
18#endif
19
20#include <utils/Pipe.h>
21#include <stdlib.h>
22#include <cutils/uio.h>
23
24// Defined in LogBundle.h.
25struct android_LogBundle;
26
27namespace android {
28
29/*
30 * A single message, which can be filled out and sent, or filled with
31 * received data.
32 *
33 * Message objects are reusable.
34 */
35class Message {
36public:
37 Message(void)
38 : mCleanup(kCleanupUnknown)
39 { reset(); }
40 ~Message(void) { reset(); }
41
42 /* values for message type byte */
43 typedef enum MessageType {
44 kTypeUnknown = 0,
45 kTypeRaw, // chunk of raw data
46 kTypeConfig, // send a name=value pair to peer
47 kTypeCommand, // simple command w/arg
48 kTypeCommandExt, // slightly more complicated command
49 kTypeLogBundle, // multi-part log message
50 } MessageType;
51
52 /* what to do with data when we're done */
53 typedef enum Cleanup {
54 kCleanupUnknown = 0,
55 kCleanupNoDelete, // do not delete data when object destroyed
56 kCleanupDelete, // delete with "delete[]"
57 } Cleanup;
58
59 /*
60 * Stuff raw data into the object. The caller can use the "cleanup"
61 * parameter to decide whether or not the Message object owns the data.
62 */
63 void setRaw(const unsigned char* data, int len, Cleanup cleanup);
64
65 /*
66 * Send a "name=value" pair.
67 */
68 void setConfig(const char* name, const char* value);
69
70 /*
71 * Send a command/arg pair.
72 */
73 void setCommand(int cmd, int arg);
74 void setCommandExt(int cmd, int arg0, int arg1, int arg2);
75
76 /*
77 * Send a multi-part log message.
78 */
79 void setLogBundle(const android_LogBundle* pBundle);
80
81 /*
82 * Simple accessors.
83 */
84 MessageType getType(void) const { return mType; }
85 const unsigned char* getData(void) const { return mData; }
86 int getLength(void) const { return mLength; }
87
88 /*
89 * Not-so-simple accessors. These coerce the raw data into an object.
90 *
91 * The data returned by these may not outlive the Message, so make
92 * copies if you plan to use them long-term.
93 */
94 bool getConfig(const char** pName, const char** pValue);
95 bool getCommand(int* pCmd, int* pArg);
96 bool getLogBundle(android_LogBundle* pBundle);
97
98 /*
99 * Read or write this message on the specified pipe.
100 *
101 * If "wait" is true, read() blocks until a message arrives. Only
102 * one thread should be reading at a time.
103 */
104 bool read(Pipe* pPipe, bool wait);
105 bool write(Pipe* pPipe) const;
106
107private:
108 Message& operator=(const Message&); // not defined
109 Message(const Message&); // not defined
110
111 void reset(void) {
112 if (mCleanup == kCleanupDelete)
113 delete[] mData;
114
115 mType = kTypeUnknown;
116 mCleanup = kCleanupNoDelete;
117 mData = NULL;
118 mLength = -1;
119 }
120
121 MessageType mType;
122 Cleanup mCleanup;
123 unsigned char* mData;
124 int mLength;
125 struct iovec mVec;
126};
127
128
129/*
130 * Abstraction of higher-level communication channel.
131 *
132 * This may be used from multiple threads simultaneously. Blocking on
133 * the read pipe from multiple threads will have unpredictable behavior.
134 *
135 * Does not take ownership of the pipes passed in to init().
136 */
137class MessageStream {
138public:
139 MessageStream(void)
140 : mReadPipe(NULL), mWritePipe(NULL)
141 {}
142 ~MessageStream(void) {}
143
144 /*
145 * Initialize object and exchange greetings. "initateHello" determines
146 * whether we send "Hello" or block waiting for it to arrive. Usually
147 * the "parent" initiates.
148 */
149 bool init(Pipe* readPipe, Pipe* writePipe, bool initiateHello);
150
151 bool isReady(void) const { return mReadPipe != NULL && mWritePipe != NULL; }
152
153 /*
154 * Send a message immediately.
155 */
156 bool send(const Message* pMsg) { return pMsg->write(mWritePipe); }
157
158 /*
159 * Receive a message.
160 */
161 bool recv(Message* pMsg, bool wait) { return pMsg->read(mReadPipe, wait); }
162
163 /*
164 * Close communication pipes. Further attempts to send or receive
165 * will fail. Note this doesn't actually "close" the pipes, because
166 * we don't own them.
167 */
168 void close(void) { mReadPipe = mWritePipe = NULL; }
169
170 /*
171 * Get our incoming traffic pipe. This is useful on Linux systems
172 * because it allows access to the file descriptor which can be used
173 * in a select() call.
174 */
175 Pipe* getReadPipe(void) { return mReadPipe; }
176
177private:
178 enum {
179 kHelloMsg = 0x4e303047, // 'N00G'
180 kHelloAckMsg = 0x31455221, // '1ER!'
181 };
182
183 /* communication pipes; note we don't own these */
184 Pipe* mReadPipe;
185 Pipe* mWritePipe;
186};
187
188}; // namespace android
189
190#endif // _LIBS_UTILS_MESSAGE_STREAM_H