msg.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /** @file msg.c
  2. * @brief Class represents a single message for custom protocol.
  3. *
  4. * Message consist of main header, a block of parameter headers and then
  5. * parameters themselfs. Class stores these data. Additionally class knows
  6. * the structure of message and can send and receive messages via socket. It
  7. * uses external faux_net_t object to do so. The receive function is necessary
  8. * because message has a variable length and message parsing is needed to get
  9. * actual length of message. The send function is usefull because class uses
  10. * struct iovec array to compose outgoing message so it's not necessary to
  11. * assemble message into the single long memory chunk.
  12. */
  13. #include <stdlib.h>
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <assert.h>
  18. #include <unistd.h>
  19. #include <errno.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <fcntl.h>
  23. #include <sys/socket.h>
  24. #include <sys/un.h>
  25. #include <arpa/inet.h>
  26. #include <faux/faux.h>
  27. #include <faux/str.h>
  28. #include <faux/list.h>
  29. #include <faux/net.h>
  30. #include <faux/msg.h>
  31. // Global variable to switch debug on/off (true/false)
  32. bool_t faux_msg_debug_flag = BOOL_FALSE;
  33. /** @brief Opaque faux_msg_s structure. */
  34. struct faux_msg_s {
  35. faux_hdr_t *hdr; // Message header
  36. faux_list_t *params; // List of parameters
  37. };
  38. static void faux_msg_set_len(faux_msg_t *msg, uint32_t len);
  39. static void faux_msg_set_param_num(faux_msg_t *msg, uint32_t param_num);
  40. /** @brief Allocate memory to store message.
  41. *
  42. * This static function is needed because new message object can be created
  43. * in a different ways. The first way is creating outgoing message manually and
  44. * the second way is receiving message from network. These ways need
  45. * different initialization but the same memory allocation.
  46. *
  47. * @return Allocated but not fully initialized faux_msg_t object
  48. * or NULL on error
  49. */
  50. static faux_msg_t *faux_msg_allocate(void)
  51. {
  52. faux_msg_t *msg = NULL;
  53. msg = faux_zmalloc(sizeof(*msg));
  54. assert(msg);
  55. if (!msg)
  56. return NULL;
  57. // Init message header
  58. msg->hdr = faux_zmalloc(sizeof(*msg->hdr));
  59. assert(msg->hdr);
  60. if (!msg->hdr) {
  61. faux_msg_free(msg);
  62. return NULL;
  63. }
  64. msg->params = faux_list_new(
  65. FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE, NULL, NULL, faux_free);
  66. return msg;
  67. }
  68. /** @brief Creates new faux_msg_t object. It's usually outgoing message.
  69. *
  70. * Function initializes main message header with default values. Usually
  71. * only outgoing messages need initialized header.
  72. *
  73. * @param [in] magic Protocol's magic number.
  74. * @param [in] major Protocol's version major number.
  75. * @param [in] minor Protocol's version minor number.
  76. * @return Allocated and initilized faux_msg_t object or NULL on error.
  77. */
  78. faux_msg_t *faux_msg_new(uint32_t magic, uint8_t major, uint8_t minor)
  79. {
  80. faux_msg_t *msg = NULL;
  81. msg = faux_msg_allocate();
  82. assert(msg);
  83. if (!msg)
  84. return NULL;
  85. // Init
  86. msg->hdr->magic = htonl(magic);
  87. msg->hdr->major = major;
  88. msg->hdr->minor = minor;
  89. faux_msg_set_cmd(msg, 0);
  90. faux_msg_set_status(msg, 0);
  91. faux_msg_set_req_id(msg, 0l);
  92. faux_msg_set_param_num(msg, 0l);
  93. faux_msg_set_len(msg, sizeof(*msg->hdr));
  94. return msg;
  95. }
  96. /** @brief Frees allocated message.
  97. *
  98. * @param [in] msg Allocated faux_msg_t object.
  99. */
  100. void faux_msg_free(faux_msg_t *msg)
  101. {
  102. if (!msg)
  103. return;
  104. faux_list_free(msg->params);
  105. faux_free(msg->hdr);
  106. faux_free(msg);
  107. }
  108. /** @brief Sets command code to header.
  109. *
  110. * See the protocol and header description for possible values.
  111. *
  112. * @param [in] msg Allocated faux_msg_t object.
  113. * @param [in] cmd Command code (16 bit).
  114. */
  115. void faux_msg_set_cmd(faux_msg_t *msg, uint16_t cmd)
  116. {
  117. assert(msg);
  118. assert(msg->hdr);
  119. if (!msg || !msg->hdr)
  120. return;
  121. msg->hdr->cmd = htons(cmd);
  122. }
  123. /** @brief Gets command code from header.
  124. *
  125. * See the protocol and header description for possible values.
  126. *
  127. * @param [in] msg Allocated faux_msg_t object.
  128. * @return Command code or 0 on error.
  129. */
  130. uint16_t faux_msg_get_cmd(const faux_msg_t *msg)
  131. {
  132. assert(msg);
  133. assert(msg->hdr);
  134. if (!msg || !msg->hdr)
  135. return 0;
  136. return ntohs(msg->hdr->cmd);
  137. }
  138. /** @brief Sets message status to header.
  139. *
  140. * See the protocol and header description for possible values.
  141. *
  142. * @param [in] msg Allocated faux_msg_t object.
  143. * @param [in] status Message status.
  144. */
  145. void faux_msg_set_status(faux_msg_t *msg, uint32_t status)
  146. {
  147. assert(msg);
  148. assert(msg->hdr);
  149. if (!msg || !msg->hdr)
  150. return;
  151. msg->hdr->status = htonl(status);
  152. }
  153. /** @brief Gets message status from header.
  154. *
  155. * See the protocol and header description for possible values.
  156. *
  157. * @param [in] msg Allocated faux_msg_t object.
  158. * @return Message status or 0 on error.
  159. */
  160. uint32_t faux_msg_get_status(const faux_msg_t *msg)
  161. {
  162. assert(msg);
  163. assert(msg->hdr);
  164. if (!msg || !msg->hdr)
  165. return 0;
  166. return ntohl(msg->hdr->status);
  167. }
  168. /** @brief Sets request ID to header.
  169. *
  170. * @param [in] msg Allocated faux_msg_t object.
  171. * @param [in] req_id Request ID.
  172. */
  173. void faux_msg_set_req_id(faux_msg_t *msg, uint32_t req_id)
  174. {
  175. assert(msg);
  176. assert(msg->hdr);
  177. if (!msg || !msg->hdr)
  178. return;
  179. msg->hdr->req_id = htonl(req_id);
  180. }
  181. /** @brief Gets request ID from header.
  182. *
  183. * @param [in] msg Allocated faux_msg_t object.
  184. * @return Request ID or 0 on error.
  185. */
  186. uint32_t faux_msg_get_req_id(const faux_msg_t *msg)
  187. {
  188. assert(msg);
  189. assert(msg->hdr);
  190. if (!msg || !msg->hdr)
  191. return 0;
  192. return ntohl(msg->hdr->req_id);
  193. }
  194. /** @brief Sets number of parameters to header.
  195. *
  196. * It's a static function because external user can add or remove parameters
  197. * but class calculates total number of parameters internally.
  198. *
  199. * @param [in] msg Allocated faux_msg_t object.
  200. * @param [in] param_num Number of parameters.
  201. */
  202. static void faux_msg_set_param_num(faux_msg_t *msg, uint32_t param_num)
  203. {
  204. assert(msg);
  205. assert(msg->hdr);
  206. if (!msg || !msg->hdr)
  207. return;
  208. msg->hdr->param_num = htonl(param_num);
  209. }
  210. /** @brief Gets number of parameters from header.
  211. *
  212. * @param [in] msg Allocated faux_msg_t object.
  213. * @return Number of parameters or 0 on error.
  214. */
  215. uint32_t faux_msg_get_param_num(const faux_msg_t *msg)
  216. {
  217. assert(msg);
  218. assert(msg->hdr);
  219. if (!msg || !msg->hdr)
  220. return -1;
  221. return ntohl(msg->hdr->param_num);
  222. }
  223. /** @brief Sets total length of message to header.
  224. *
  225. * It's a static function because external user can add or remove parameters
  226. * but class calculates total length of message internally.
  227. *
  228. * @param [in] msg Allocated faux_msg_t object.
  229. * @param [in] len Total length of message.
  230. */
  231. static void faux_msg_set_len(faux_msg_t *msg, uint32_t len)
  232. {
  233. assert(msg);
  234. assert(msg->hdr);
  235. if (!msg || !msg->hdr)
  236. return;
  237. msg->hdr->len = htonl(len);
  238. }
  239. /** @brief Gets total length of message from header.
  240. *
  241. * @param [in] msg Allocated faux_msg_t object.
  242. * @return Total length of message or 0 on error.
  243. */
  244. int faux_msg_get_len(const faux_msg_t *msg)
  245. {
  246. assert(msg);
  247. assert(msg->hdr);
  248. if (!msg || !msg->hdr)
  249. return 0;
  250. return ntohl(msg->hdr->len);
  251. }
  252. /** @brief Gets magic number from header.
  253. *
  254. * @param [in] msg Allocated faux_msg_t object.
  255. * @return Magic number or 0 on error.
  256. */
  257. uint32_t faux_msg_get_magic(const faux_msg_t *msg)
  258. {
  259. assert(msg);
  260. assert(msg->hdr);
  261. if (!msg || !msg->hdr)
  262. return 0;
  263. return ntohl(msg->hdr->magic);
  264. }
  265. /** @brief Gets major version from header.
  266. *
  267. * @param [in] msg Allocated faux_msg_t object.
  268. * @return Major version number or 0 on error.
  269. */
  270. int faux_msg_get_major(const faux_msg_t *msg)
  271. {
  272. assert(msg);
  273. assert(msg->hdr);
  274. if (!msg || !msg->hdr)
  275. return 0;
  276. return msg->hdr->major;
  277. }
  278. /** @brief Gets minor version from header.
  279. *
  280. * @param [in] msg Allocated faux_msg_t object.
  281. * @return Minor version number or 0 on error.
  282. */
  283. int faux_msg_get_minor(const faux_msg_t *msg)
  284. {
  285. assert(msg);
  286. assert(msg->hdr);
  287. if (!msg || !msg->hdr)
  288. return 0;
  289. return msg->hdr->minor;
  290. }
  291. /** @brief Internal function to add message parameter
  292. *
  293. * Internal function can update or don't update number of parameters and
  294. * whole length within message header. It can be used while
  295. * message receive to don't break already calculated header
  296. * values. So when user is constructing message the values must be updated.
  297. *
  298. * @param [in] msg Allocated faux_msg_t object.
  299. * @param [in] type Type of parameter.
  300. * @param [in] buf Parameter's data buffer.
  301. * @param [in] len Parameter's data length.
  302. * @param [in] upadte_len Flag that says to update or don't update number of
  303. * parameters and total message length within header. BOOL_TRUE - update,
  304. * BOOL_FALSE - don't update.
  305. * @return Length of parameter's data or < 0 on error.
  306. */
  307. static ssize_t faux_msg_add_param_internal(faux_msg_t *msg,
  308. uint16_t type, const void *buf, size_t len, bool_t update_len)
  309. {
  310. faux_phdr_t *phdr = NULL;
  311. char *param = NULL;
  312. assert(msg);
  313. assert(msg->hdr);
  314. if (!msg || !msg->hdr)
  315. return -1;
  316. // Allocate parameter header and data
  317. param = faux_zmalloc(sizeof(*phdr) + len);
  318. assert(param);
  319. if (!param)
  320. return -1;
  321. // Init param hdr
  322. phdr = (faux_phdr_t *)param;
  323. faux_phdr_set_type(phdr, type);
  324. faux_phdr_set_len(phdr, len);
  325. // Copy data
  326. memcpy(param + sizeof(*phdr), buf, len);
  327. if (update_len) {
  328. // Update number of parameters
  329. faux_msg_set_param_num(msg, faux_msg_get_param_num(msg) + 1);
  330. // Update whole message length
  331. faux_msg_set_len(msg,
  332. faux_msg_get_len(msg) + sizeof(*phdr) + len);
  333. }
  334. // Add to parameter list
  335. faux_list_add(msg->params, param);
  336. return len;
  337. }
  338. /** @brief Adds parameter to message.
  339. *
  340. * @param [in] msg Allocated faux_msg_t object.
  341. * @param [in] type Type of parameter.
  342. * @param [in] buf Parameter's data buffer.
  343. * @param [in] len Parameter's data length.
  344. * @return Length of parameter's data or < 0 on error.
  345. */
  346. ssize_t faux_msg_add_param(faux_msg_t *msg, uint16_t type,
  347. const void *buf, size_t len)
  348. {
  349. return faux_msg_add_param_internal(msg, type, buf, len, BOOL_TRUE);
  350. }
  351. /** @brief Initializes iterator to iterate through the message parameters.
  352. *
  353. * The iterator must be initialized before iteration.
  354. *
  355. * @param [in] msg Allocated faux_msg_t object.
  356. * @return Initialized iterator.
  357. */
  358. faux_list_node_t *faux_msg_init_param_iter(const faux_msg_t *msg)
  359. {
  360. assert(msg);
  361. assert(msg->params);
  362. if (!msg || !msg->params)
  363. return NULL;
  364. return faux_list_head(msg->params);
  365. }
  366. /** @brief Internal function to get parameter's data by node (faux_list_node_t).
  367. *
  368. * Note function returns the main data by output arguments.
  369. *
  370. * @param [in] node Node from the parameter's list.
  371. * @param [out] param_type Type of parameter.
  372. * @param [out] param_buf Parameter's data buffer.
  373. * @param [out] param_len Parameter's data length.
  374. * @return Pointer to parameter's header or NULL on error.
  375. */
  376. static faux_phdr_t *faux_msg_get_param_by_node(const faux_list_node_t *node,
  377. uint16_t *param_type, void **param_data, uint32_t *param_len)
  378. {
  379. char *param = NULL;
  380. faux_phdr_t *phdr = NULL;
  381. char *data = NULL;
  382. if (!node)
  383. return NULL;
  384. param = faux_list_data(node);
  385. phdr = (faux_phdr_t *)param;
  386. data = param + sizeof(*phdr);
  387. if (param_type)
  388. *param_type = faux_phdr_get_type(phdr);
  389. if (param_len)
  390. *param_len = faux_phdr_get_len(phdr);
  391. if (param_data)
  392. *param_data = data;
  393. return phdr;
  394. }
  395. /** @brief Iterate through the message parameters.
  396. *
  397. * First parameter (iterator/node) must be initialized first by
  398. * faux_msg_init_param_iter().
  399. *
  400. * @param [in] node Initialized iterator of parameter list.
  401. * @param [out] param_type Type of parameter.
  402. * @param [out] param_buf Parameter's data buffer.
  403. * @param [out] param_len Parameter's data length.
  404. * @return Pointer to parameter's header or NULL on error.
  405. */
  406. faux_phdr_t *faux_msg_get_param_each(faux_list_node_t **node,
  407. uint16_t *param_type, void **param_data, uint32_t *param_len)
  408. {
  409. faux_list_node_t *current_node = NULL;
  410. if (!node || !*node)
  411. return NULL;
  412. current_node = *node;
  413. *node = faux_list_next_node(current_node);
  414. return faux_msg_get_param_by_node(current_node,
  415. param_type, param_data, param_len);
  416. }
  417. /** @brief Gets message parameter by the index.
  418. *
  419. * @param [in] msg Allocated faux_msg_t object.
  420. * @param [in] index Parameter's index.
  421. * @param [out] param_type Type of parameter.
  422. * @param [out] param_buf Parameter's data buffer.
  423. * @param [out] param_len Parameter's data length.
  424. * @return Pointer to parameter's header or NULL on error.
  425. */
  426. faux_phdr_t *faux_msg_get_param_by_index(const faux_msg_t *msg, unsigned int index,
  427. uint16_t *param_type, void **param_data, uint32_t *param_len)
  428. {
  429. faux_list_node_t *iter = NULL;
  430. unsigned int i = 0;
  431. assert(msg);
  432. assert(msg->hdr);
  433. if (!msg || !msg->hdr)
  434. return NULL;
  435. if (index >= faux_msg_get_param_num(msg)) // Non-existent entry
  436. return NULL;
  437. iter = faux_msg_init_param_iter(msg);
  438. while ((i != index) && iter) {
  439. i++;
  440. iter = faux_list_next_node(iter);
  441. }
  442. return faux_msg_get_param_by_node(iter,
  443. param_type, param_data, param_len);
  444. }
  445. /** @brief Gets message parameter by parameter's type.
  446. *
  447. * Note message can contain many parameters with the same type. This function
  448. * will find only the first parameter with specified type. You can iterate
  449. * through all parameters to find all entries with type you need.
  450. *
  451. * @param [in] msg Allocated faux_msg_t object.
  452. * @param [in] param_type Type of parameter.
  453. * @param [out] param_buf Parameter's data buffer.
  454. * @param [out] param_len Parameter's data length.
  455. * @return Pointer to parameter's header or NULL on error.
  456. */
  457. faux_phdr_t *faux_msg_get_param_by_type(const faux_msg_t *msg,
  458. uint16_t param_type, void **param_data, uint32_t *param_len)
  459. {
  460. faux_list_node_t *iter = NULL;
  461. assert(msg);
  462. assert(msg->hdr);
  463. if (!msg || !msg->hdr)
  464. return NULL;
  465. for (iter = faux_msg_init_param_iter(msg);
  466. iter; iter = faux_list_next_node(iter)) {
  467. faux_phdr_t *phdr = NULL;
  468. phdr = (faux_phdr_t *)faux_list_data(iter);
  469. if (faux_phdr_get_type(phdr) == param_type)
  470. return faux_msg_get_param_by_node(iter,
  471. NULL, param_data, param_len);
  472. }
  473. // Not found
  474. return NULL;
  475. }
  476. /** @brief Sends message to network.
  477. *
  478. * Function sends message to network using preinitialized faux_net_t object.
  479. * User can specify timeout, signal mask, etc while faux_net_t object creation.
  480. *
  481. * Function can return length less than whole message length in the following
  482. * cases:
  483. * - An error has occured like broken file descriptor.
  484. * - Interrupted by allowed signal (see signal mask).
  485. * - Timeout.
  486. *
  487. * @param [in] msg Allocated faux_msg_t object.
  488. * @param [in] faux_net Preinitialized faux_net_t object.
  489. * @return Length of sent data or < 0 on error.
  490. */
  491. ssize_t faux_msg_send(faux_msg_t *msg, faux_net_t *faux_net)
  492. {
  493. unsigned int vec_entries_num = 0;
  494. struct iovec *iov = NULL;
  495. unsigned int i = 0;
  496. faux_list_node_t *iter = NULL;
  497. size_t ret = 0;
  498. assert(msg);
  499. assert(msg->hdr);
  500. if (!msg || !msg->hdr)
  501. return -1;
  502. // Calculate number if struct iovec entries.
  503. // n = (msg header) + ((param hdr) + (param data)) * (param_num)
  504. vec_entries_num = 1 + (2 * faux_msg_get_param_num(msg));
  505. iov = faux_zmalloc(vec_entries_num * sizeof(*iov));
  506. // Message header
  507. iov[i].iov_base = msg->hdr;
  508. iov[i].iov_len = sizeof(*msg->hdr);
  509. i++;
  510. // Parameter headers
  511. for (iter = faux_msg_init_param_iter(msg);
  512. iter; iter = faux_list_next_node(iter)) {
  513. faux_phdr_t *phdr = NULL;
  514. phdr = (faux_phdr_t *)faux_list_data(iter);
  515. iov[i].iov_base = phdr;
  516. iov[i].iov_len = sizeof(*phdr);
  517. i++;
  518. }
  519. // Parameter data
  520. for (iter = faux_msg_init_param_iter(msg);
  521. iter; iter = faux_list_next_node(iter)) {
  522. faux_phdr_t *phdr = NULL;
  523. void *data = NULL;
  524. phdr = (faux_phdr_t *)faux_list_data(iter);
  525. data = (char *)phdr + sizeof(*phdr);
  526. iov[i].iov_base = data;
  527. iov[i].iov_len = faux_phdr_get_len(phdr);
  528. i++;
  529. }
  530. ret = faux_net_sendv(faux_net, iov, vec_entries_num);
  531. faux_free(iov);
  532. #ifdef DEBUG
  533. // Debug
  534. if (msg && ret > 0 && faux_msg_debug_flag) {
  535. printf("(o) ");
  536. faux_msg_debug(msg);
  537. }
  538. #endif
  539. return ret;
  540. }
  541. /** @brief Receives full message and allocates faux_msg_t object for it.
  542. *
  543. * Function receives message from network using preinitialized faux_net_t object.
  544. * User can specify timeout, signal mask, etc while faux_net_t object creation.
  545. *
  546. * Function can return length less than whole message length in the following
  547. * cases:
  548. * - An error has occured like broken file descriptor.
  549. * - Interrupted by allowed signal (see signal mask).
  550. * - Timeout.
  551. *
  552. * @param [in] faux_net Preinitialized faux_net_t object.
  553. * @param [out] status Status while message receiving. Can be NULL.
  554. * @return Allocated faux_msg_t object. Object contains received message.
  555. */
  556. faux_msg_t *faux_msg_recv(faux_net_t *faux_net)
  557. {
  558. faux_msg_t *msg = NULL;
  559. size_t received = 0;
  560. faux_phdr_t *phdr = NULL;
  561. size_t phdr_whole_len = 0;
  562. size_t max_data_len = 0;
  563. unsigned int i = 0;
  564. char *data = NULL;
  565. uint32_t param_num = 0;
  566. msg = faux_msg_allocate();
  567. assert(msg);
  568. if (!msg)
  569. return NULL;
  570. // Receive message header
  571. received = faux_net_recv(faux_net, msg->hdr, sizeof(*msg->hdr));
  572. if (received != sizeof(*msg->hdr)) {
  573. faux_msg_free(msg);
  574. return NULL;
  575. }
  576. // Receive parameter headers
  577. param_num = faux_msg_get_param_num(msg);
  578. if (param_num != 0) {
  579. phdr_whole_len = param_num * sizeof(*phdr);
  580. phdr = faux_zmalloc(phdr_whole_len);
  581. received = faux_net_recv(faux_net, phdr, phdr_whole_len);
  582. if (received != phdr_whole_len) {
  583. faux_free(phdr);
  584. faux_msg_free(msg);
  585. return NULL;
  586. }
  587. // Find out maximum data length
  588. for (i = 0; i < param_num; i++) {
  589. size_t cur_data_len = faux_phdr_get_len(phdr + i);
  590. if (cur_data_len > max_data_len)
  591. max_data_len = cur_data_len;
  592. }
  593. // Receive parameter data
  594. data = faux_zmalloc(max_data_len);
  595. for (i = 0; i < param_num; i++) {
  596. size_t cur_data_len = faux_phdr_get_len(phdr + i);
  597. if (0 == cur_data_len)
  598. continue;
  599. received = faux_net_recv(faux_net, data, cur_data_len);
  600. if (received != cur_data_len) {
  601. faux_free(data);
  602. faux_free(phdr);
  603. faux_msg_free(msg);
  604. return NULL;
  605. }
  606. faux_msg_add_param_internal(msg,
  607. faux_phdr_get_type(phdr + i),
  608. data, cur_data_len, BOOL_FALSE);
  609. }
  610. faux_free(data);
  611. faux_free(phdr);
  612. }
  613. #ifdef DEBUG
  614. // Debug
  615. if (msg && faux_msg_debug_flag) {
  616. printf("(i) ");
  617. faux_msg_debug(msg);
  618. }
  619. #endif
  620. return msg;
  621. }
  622. /** @brief Prints message debug info.
  623. *
  624. * Function prints header values and parameters.
  625. *
  626. * @param [in] msg Allocated faux_msg_t object.
  627. */
  628. void faux_msg_debug(faux_msg_t *msg)
  629. #ifdef DEBUG
  630. {
  631. faux_list_node_t *iter = 0;
  632. // Parameter vars
  633. void *param_data = NULL;
  634. uint16_t param_type = 0;
  635. uint32_t param_len = 0;
  636. assert(msg);
  637. if (!msg)
  638. return;
  639. // Header
  640. printf("%lx(%u.%u): c%04x s%08x i%08x p%u l%u |%lub\n",
  641. faux_msg_get_magic(msg),
  642. faux_msg_get_major(msg),
  643. faux_msg_get_minor(msg),
  644. faux_msg_get_cmd(msg),
  645. faux_msg_get_status(msg),
  646. faux_msg_get_req_id(msg),
  647. faux_msg_get_param_num(msg),
  648. faux_msg_get_len(msg),
  649. sizeof(*msg->hdr)
  650. );
  651. // Parameters
  652. iter = faux_msg_init_param_iter(msg);
  653. while (faux_msg_get_param_each(&iter, &param_type, &param_data, &param_len)) {
  654. printf(" t%04x l%u |%lub\n",
  655. param_type,
  656. param_len,
  657. sizeof(faux_phdr_t) + param_len
  658. );
  659. }
  660. }
  661. #else
  662. {
  663. msg = msg; // Happy compiler
  664. }
  665. #endif