• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
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 "Pipe.h"
21 #include <stdlib.h>
22 #include <cutils/uio.h>
23 
24 // Defined in LogBundle.h.
25 struct android_LogBundle;
26 
27 namespace 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  */
35 class Message {
36 public:
Message(void)37     Message(void)
38         : mCleanup(kCleanupUnknown)
39         { reset(); }
~Message(void)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      */
getType(void)84     MessageType getType(void) const { return mType; }
getData(void)85     const unsigned char* getData(void) const { return mData; }
getLength(void)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 
107 private:
108     Message& operator=(const Message&);     // not defined
109     Message(const Message&);                // not defined
110 
reset(void)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  */
137 class MessageStream {
138 public:
MessageStream(void)139     MessageStream(void)
140         : mReadPipe(NULL), mWritePipe(NULL)
141         {}
~MessageStream(void)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 
isReady(void)151     bool isReady(void) const { return mReadPipe != NULL && mWritePipe != NULL; }
152 
153     /*
154      * Send a message immediately.
155      */
send(const Message * pMsg)156     bool send(const Message* pMsg) { return pMsg->write(mWritePipe); }
157 
158     /*
159      * Receive a message.
160      */
recv(Message * pMsg,bool wait)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      */
close(void)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      */
getReadPipe(void)175     Pipe* getReadPipe(void) { return mReadPipe; }
176 
177 private:
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
191