ipc_codec.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. // Copyright (c) 2010 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef SIMPLE_IPC_CODEC_H_
  15. #define SIMPLE_IPC_CODEC_H_
  16. #include "os_includes.h"
  17. ///////////////////////////////////////////////////////////////////////////////////////////////////
  18. // This file contains the default encoder & decoder for IPC. It does no compression and every
  19. // encoded element is aligned to the machine word size. For a 32 bit machine, this is how the
  20. // format on the final buffer looks like:
  21. //
  22. // bytes what
  23. // 0 start of header mark
  24. // 4 msg id
  25. // 8 element count (1 to N)
  26. // 12 data count (in 4 byte units
  27. // 16 first element tag
  28. // 20 second element tag
  29. // +4 .......
  30. // last element type
  31. // start of data mark
  32. // first element value
  33. // second element value
  34. // .......
  35. // end of data mark
  36. //
  37. // As you can see the element tags are not interleaved with the element value, all the tags
  38. // are within the header, and all values follow afterwards.
  39. //
  40. // This code does not assume any knowledge of the Channel type. For example is unaware of WireType
  41. // so it takes a generic |tag| that in the case of using it with the standard ipc::Channel they
  42. // would be ipc::TYPE_XXXXX. However, arrays (bytes and strings) are treated differently in which
  43. // the tag is actually 'enhanced' with an extra bit in the form of ENC_STRN08 or ENC_STRN16.
  44. namespace ipc {
  45. class Encoder {
  46. public:
  47. enum {
  48. ENC_HEADER = 0x4d4f524b,
  49. ENC_STARTD = 0x4b524f4d,
  50. ENC_ENDDAT = 0x474e4142,
  51. ENC_STRN08 = 1<<30,
  52. ENC_STRN16 = 1<<31
  53. };
  54. Encoder() : index_(-1) {}
  55. bool Open(int count) {
  56. data_.clear();
  57. data_.reserve(count * 5);
  58. data_.resize(count + 5);
  59. index_ = -1;
  60. SetHeaderNext(ENC_HEADER); // 0
  61. SetHeaderNext(0); // 1
  62. SetHeaderNext(count); // 2
  63. SetHeaderNext(0); // 3
  64. return true;
  65. }
  66. bool Close() {
  67. SetHeaderNext(ENC_STARTD);
  68. PushBack(ENC_ENDDAT);
  69. SetDataSizeHeader();
  70. return true;
  71. }
  72. bool OnWord(void* bits, int tag) {
  73. SetHeaderNext(tag);
  74. data_.push_back(bits);
  75. return true;
  76. };
  77. bool OnString8(const IPCString& s, int tag) {
  78. SetHeaderNext(tag | ENC_STRN08);
  79. PushBack(s.size());
  80. if (s.size()) AddStr(s);
  81. return true;
  82. }
  83. bool OnString16(const IPCWString& s, int tag) {
  84. SetHeaderNext(tag | ENC_STRN16);
  85. PushBack(s.size());
  86. if (s.size()) AddStr(s);
  87. return true;
  88. }
  89. bool OnUnixFd(int /*fd*/, int tag) {
  90. SetHeaderNext(tag);
  91. // $$ implement
  92. return true;
  93. }
  94. bool OnWinHandle(void* /*handle*/, int tag) {
  95. SetHeaderNext(tag);
  96. // $$ implement
  97. return true;
  98. }
  99. const void* GetBuffer(size_t* sz) {
  100. *sz = data_.size() * sizeof(void*);
  101. return &data_[0];
  102. }
  103. void SetMsgId(int id) {
  104. data_[1] = reinterpret_cast<void*>(id);
  105. }
  106. private:
  107. void SetHeaderNext(int v) {
  108. data_[++index_] = reinterpret_cast<void*>(v);
  109. }
  110. void SetDataSizeHeader() {
  111. data_[3] = reinterpret_cast<void*>(data_.size());
  112. }
  113. void PushBack(int v) {
  114. data_.push_back(reinterpret_cast<void*>(v));
  115. }
  116. void PushBack(unsigned int v) {
  117. data_.push_back(reinterpret_cast<void*>(v));
  118. }
  119. template <typename StringT>
  120. void AddStr(const StringT& s ) {
  121. const int times = sizeof(IPCVoidPtrVector::value_type) / sizeof(s[0]);
  122. size_t it = 0;
  123. do {
  124. unsigned int v = 0;
  125. for (int ix = 0; ix != times; ++ix) {
  126. if (it == s.size())
  127. break;
  128. v |= PackChar(s[it], ix);
  129. ++it;
  130. }
  131. PushBack(v);
  132. } while (it != s.size());
  133. }
  134. unsigned int PackChar(char c, int offset) const {
  135. return static_cast<unsigned char>(c) << (offset * 8);
  136. }
  137. #if 0
  138. unsigned int PackChar(wchar_t c, int offset) const {
  139. unsigned int u = (static_cast<unsigned char>(c) << 8) | static_cast<unsigned char>(c >> 8)
  140. return u << offset * 16;
  141. }
  142. #endif
  143. unsigned int PackChar(wchar_t c, int offset) const {
  144. const char* t = reinterpret_cast<const char*>(&c);
  145. return (PackChar(t[0], 0) | PackChar(t[1], 1)) << (offset * 16);
  146. }
  147. IPCVoidPtrVector data_;
  148. int index_;
  149. };
  150. template <typename HandlerT>
  151. class Decoder {
  152. public:
  153. Decoder(HandlerT* handler) : handler_(handler) {
  154. Reset();
  155. }
  156. bool OnData(const char* buff, size_t sz) {
  157. if (buff) {
  158. data_.insert(data_.end(), buff, buff + sz);
  159. } else if (!data_.size()) {
  160. return true;
  161. }
  162. if (data_.size() % sizeof(void*) == 0) {
  163. return (RunDecoder() == DEC_MOREDATA);
  164. }
  165. return true;
  166. }
  167. bool Success() { return state_ == DEC_S_DONE; }
  168. bool NeedsMoreData() const {
  169. return (data_.size() == 0) || (res_ == DEC_MOREDATA);
  170. }
  171. void Reset() {
  172. state_ = DEC_S_START;
  173. e_count_ = -1;
  174. d_count_ = static_cast<size_t>(-1);
  175. next_char_ = 0;
  176. res_ = DEC_NONE;
  177. }
  178. private:
  179. // States of the decoder state machine, for a single message
  180. // they are basically traveled from the first to the last and
  181. // there is no state that means 'error'. When an error happens
  182. // the state machine stops at the state that caused it.
  183. enum State {
  184. DEC_S_START,
  185. DEC_S_HEADSZ,
  186. DEC_S_EDATA,
  187. DEC_S_STOP,
  188. DEC_S_DONE
  189. };
  190. // The possible results of running one step on the state machine.
  191. // DEC_LOOPAGAIN causes the state machine to be spin up one more
  192. // time while the others cause it to return to the caller so
  193. // it can provide more data, handle a decoding error or process
  194. // a ready message.
  195. enum Result {
  196. DEC_NONE,
  197. DEC_LOOPAGAIN,
  198. DEC_MOREDATA,
  199. DEC_DONE,
  200. DEC_ERROR
  201. };
  202. Result RunDecoder() {
  203. do {
  204. res_ = DecodeStep();
  205. } while (DEC_LOOPAGAIN == res_);
  206. return res_;
  207. }
  208. Result DecodeStep() {
  209. switch(state_) {
  210. case DEC_S_START: return StateStart();
  211. case DEC_S_HEADSZ: return StateHeader();
  212. case DEC_S_EDATA: return StateData();
  213. case DEC_S_STOP: return StateDone();
  214. default: break;
  215. }
  216. return DEC_ERROR;
  217. }
  218. Result StateStart() {
  219. // We need at least the first 4 ints.
  220. if (!HasEnoughUnProcessed(4))
  221. return DEC_MOREDATA;
  222. int i0 = ReadNextInt();
  223. if (Encoder::ENC_HEADER != i0)
  224. return DEC_ERROR;
  225. int msg_id = ReadNextInt();
  226. if (msg_id < 0)
  227. return DEC_ERROR;
  228. e_count_ = ReadNextInt();
  229. if ((e_count_ < 1) || (e_count_ > 100))
  230. return DEC_ERROR;
  231. d_count_ = ReadNextInt();
  232. if ((d_count_ < 5) || (d_count_ > (8 * 1024 * 1024)))
  233. return DEC_ERROR;
  234. // Done with the key header piece.
  235. if (!handler_->OnMessageStart(msg_id, e_count_))
  236. return DEC_ERROR;
  237. // The handler is willing to accept the message.
  238. d_count_ -= 4;
  239. state_ = DEC_S_HEADSZ;
  240. if (HasEnoughUnProcessed(1))
  241. return DEC_LOOPAGAIN;
  242. return DEC_MOREDATA;
  243. }
  244. Result StateHeader() {
  245. if (!HasEnoughUnProcessed(e_count_ + 1))
  246. return DEC_MOREDATA;
  247. //items_.reserve(e_count_);
  248. for (int ix = 0; ix != e_count_; ++ix) {
  249. items_.push_back(ReadNextInt());
  250. }
  251. int i0 = ReadNextInt();
  252. if (i0 != Encoder::ENC_STARTD)
  253. return DEC_ERROR;
  254. // Done with all the header
  255. d_count_ -= e_count_ + 1;
  256. if (!items_.size()) {
  257. // That's it, no data.
  258. state_ = DEC_S_STOP;
  259. if (HasEnoughUnProcessed(1))
  260. return DEC_LOOPAGAIN;
  261. return DEC_MOREDATA;
  262. }
  263. // We got data to process. Each datum, even null strings
  264. // take at least 4 bytes.
  265. if (d_count_ < items_.size())
  266. return DEC_ERROR;
  267. state_ = DEC_S_EDATA;
  268. if (HasEnoughUnProcessed(1))
  269. return DEC_LOOPAGAIN;
  270. return DEC_MOREDATA;
  271. }
  272. Result StateData() {
  273. if (!HasEnoughUnProcessed(d_count_))
  274. return DEC_MOREDATA;
  275. size_t ix = 0;
  276. do {
  277. int tag = items_[ix];
  278. if (tag & Encoder::ENC_STRN08) {
  279. tag &= ~Encoder::ENC_STRN08;
  280. ReadNextStr8(tag);
  281. } else if (tag & Encoder::ENC_STRN16) {
  282. tag &= ~Encoder::ENC_STRN16;
  283. ReadNextStr16(tag);
  284. } else {
  285. --d_count_;
  286. if (!handler_->OnWord(ReadNextVoidPtr(), tag)) {
  287. return DEC_ERROR;
  288. }
  289. }
  290. ++ix;
  291. if (items_.size() == ix) {
  292. items_.clear();
  293. state_ = DEC_S_STOP;
  294. if (HasEnoughUnProcessed(1))
  295. return DEC_LOOPAGAIN;
  296. return DEC_MOREDATA;
  297. }
  298. } while (HasEnoughUnProcessed(1));
  299. return DEC_MOREDATA;
  300. }
  301. Result StateDone() {
  302. if (!HasEnoughUnProcessed(1))
  303. return DEC_MOREDATA;
  304. --d_count_;
  305. int it0 = ReadNextInt();
  306. if (Encoder::ENC_ENDDAT != it0)
  307. return DEC_ERROR;
  308. data_.erase(data_.begin(), data_.begin() + next_char_);
  309. state_ = DEC_S_DONE;
  310. return DEC_DONE;
  311. }
  312. int ReadNextInt() {
  313. int v = *reinterpret_cast<int*>(&data_[next_char_]);
  314. next_char_ += sizeof(void*);
  315. return v;
  316. }
  317. bool ReadNextStr8(int tag) {
  318. size_t str_sz = ReadNextInt();
  319. size_t sz_rounded = RoundUpToNextVoidPtr(str_sz);
  320. if(!HasEnoughUnProcessed(sz_rounded))
  321. return false;
  322. const char* beg = &data_[next_char_];
  323. IPCString str;
  324. str.assign(beg, str_sz);
  325. next_char_ += sz_rounded * sizeof(void*);
  326. handler_->OnString8(str, tag);
  327. return true;
  328. }
  329. bool ReadNextStr16(int tag) {
  330. size_t str_sz = ReadNextInt();
  331. size_t byte_sz = str_sz * sizeof(wchar_t);
  332. size_t sz_rounded = RoundUpToNextVoidPtr(byte_sz);
  333. if(!HasEnoughUnProcessed(sz_rounded))
  334. return false;
  335. const wchar_t* beg = reinterpret_cast<wchar_t*>(&data_[next_char_]);
  336. IPCWString str;
  337. str.assign(beg, str_sz);
  338. next_char_ += sz_rounded * sizeof(void*);
  339. handler_->OnString16(str, tag);
  340. return true;
  341. }
  342. void* ReadNextVoidPtr() {
  343. void* v = &data_[next_char_];
  344. next_char_ += sizeof(void*);
  345. return v;
  346. }
  347. char ReadNextChar() {
  348. return data_[next_char_++];
  349. }
  350. bool HasEnoughUnProcessed(int ints) {
  351. return ((data_.size() - next_char_) >= (ints * sizeof(void*)));
  352. }
  353. int RoundUpToNextVoidPtr(int sz) {
  354. return (sz + (sizeof(void*)-1))/sizeof(void*);
  355. }
  356. HandlerT* handler_;
  357. IPCCharVector data_;
  358. IPCIntVector items_;
  359. State state_;
  360. int e_count_;
  361. size_t d_count_;
  362. int next_char_;
  363. Result res_;
  364. };
  365. } // namespace ipc.
  366. #endif // SIMPLE_IPC_CODEC_H_