msg.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  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. faux_hdr_set_magic(msg->hdr, magic);
  87. faux_hdr_set_major(msg->hdr, major);
  88. faux_hdr_set_minor(msg->hdr, 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. return faux_hdr_set_cmd(msg->hdr, 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 faux_hdr_cmd(msg->hdr);
  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. return faux_hdr_set_status(msg->hdr, 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 faux_hdr_status(msg->hdr);
  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. return faux_hdr_set_req_id(msg->hdr, 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 faux_hdr_req_id(msg->hdr);
  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. return faux_hdr_set_param_num(msg->hdr, 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 faux_hdr_param_num(msg->hdr);
  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. return faux_hdr_set_len(msg->hdr, 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 faux_hdr_len(msg->hdr);
  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 faux_hdr_magic(msg->hdr);
  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 faux_hdr_major(msg->hdr);
  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 faux_hdr_minor(msg->hdr);
  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 Create IOV of message.
  477. *
  478. * Function creates and fills iovec structure. This iovec contains references
  479. * to parts of message enough to construct message in network format.
  480. *
  481. * @param [in] msg Allocated faux_msg_t object.
  482. * @param [out] iov_out iovec structure.
  483. * @param [out] iov_num_out Number of iovec entries.
  484. * @return BOOL_TRUE - success, BOOL_FALSE - fail.
  485. */
  486. bool_t faux_msg_iov(const faux_msg_t *msg, struct iovec **iov_out, size_t *iov_num_out)
  487. {
  488. size_t vec_entries_num = 0;
  489. struct iovec *iov = NULL;
  490. unsigned int i = 0;
  491. faux_list_node_t *iter = NULL;
  492. assert(msg);
  493. if (!msg)
  494. return BOOL_FALSE;
  495. assert(msg->hdr);
  496. if (!msg->hdr)
  497. return BOOL_FALSE;
  498. assert(iov_out);
  499. if (!iov_out)
  500. return BOOL_FALSE;
  501. assert(iov_num_out);
  502. if (!iov_num_out)
  503. return BOOL_FALSE;
  504. // Calculate number if struct iovec entries.
  505. // n = (msg header) + ((param hdr) + (param data)) * (param_num)
  506. vec_entries_num = 1 + (2 * faux_msg_get_param_num(msg));
  507. iov = faux_zmalloc(vec_entries_num * sizeof(*iov));
  508. // Message header
  509. iov[i].iov_base = msg->hdr;
  510. iov[i].iov_len = sizeof(*msg->hdr);
  511. i++;
  512. // Parameter headers
  513. for (iter = faux_msg_init_param_iter(msg);
  514. iter; iter = faux_list_next_node(iter)) {
  515. faux_phdr_t *phdr = NULL;
  516. phdr = (faux_phdr_t *)faux_list_data(iter);
  517. iov[i].iov_base = phdr;
  518. iov[i].iov_len = sizeof(*phdr);
  519. i++;
  520. }
  521. // Parameter data
  522. for (iter = faux_msg_init_param_iter(msg);
  523. iter; iter = faux_list_next_node(iter)) {
  524. faux_phdr_t *phdr = NULL;
  525. void *data = NULL;
  526. phdr = (faux_phdr_t *)faux_list_data(iter);
  527. data = (char *)phdr + sizeof(*phdr);
  528. iov[i].iov_base = data;
  529. iov[i].iov_len = faux_phdr_get_len(phdr);
  530. i++;
  531. }
  532. *iov_out = iov;
  533. *iov_num_out = vec_entries_num;
  534. return BOOL_TRUE;
  535. }
  536. /** @brief Sends message to network.
  537. *
  538. * Function sends message to network using preinitialized faux_net_t object.
  539. * User can specify timeout, signal mask, etc while faux_net_t object creation.
  540. *
  541. * Function can return length less than whole message length in the following
  542. * cases:
  543. * - An error has occured like broken file descriptor.
  544. * - Interrupted by allowed signal (see signal mask).
  545. * - Timeout.
  546. *
  547. * @param [in] msg Allocated faux_msg_t object.
  548. * @param [in] faux_net Preinitialized faux_net_t object.
  549. * @return Length of sent data or < 0 on error.
  550. */
  551. ssize_t faux_msg_send(const faux_msg_t *msg, faux_net_t *faux_net)
  552. {
  553. size_t vec_entries_num = 0;
  554. struct iovec *iov = NULL;
  555. size_t ret = 0;
  556. if (!faux_msg_iov(msg, &iov, &vec_entries_num))
  557. return -1;
  558. ret = faux_net_sendv(faux_net, iov, vec_entries_num);
  559. faux_free(iov);
  560. #ifdef DEBUG
  561. // Debug
  562. if (msg && ret > 0 && faux_msg_debug_flag) {
  563. printf("(o) ");
  564. faux_msg_debug(msg);
  565. }
  566. #endif
  567. return ret;
  568. }
  569. /** @brief Serializes message.
  570. *
  571. * @param [in] msg Allocated faux_msg_t object.
  572. * @param [out] buf Serialized message.
  573. * @param [out] len Length of serialized message.
  574. * @return BOOL_TRUE - success, BOOL_FALSE - fail.
  575. */
  576. bool_t faux_msg_serialize(const faux_msg_t *msg, char **buf, size_t *len)
  577. {
  578. size_t vec_entries_num = 0;
  579. struct iovec *iov = NULL;
  580. unsigned int i = 0;
  581. size_t total_len = 0;
  582. char *buffer = NULL;
  583. char *p = NULL;
  584. if (!faux_msg_iov(msg, &iov, &vec_entries_num))
  585. return BOOL_FALSE;
  586. for (i = 0; i < vec_entries_num; i++)
  587. total_len += iov[i].iov_len;
  588. buffer = faux_malloc(total_len);
  589. p = buffer;
  590. for (i = 0; i < vec_entries_num; i++) {
  591. memcpy(p, iov[i].iov_base, iov[i].iov_len);
  592. p += iov[i].iov_len;
  593. }
  594. *buf = buffer;
  595. *len = total_len;
  596. return BOOL_TRUE;
  597. }
  598. /** @brief Deserializes message header and body to faux_msg_t structure.
  599. *
  600. * The typical case is when message is received to two buffers. The first is
  601. * a header of constant size and the second is message body with size found out
  602. * from already received message header. Function gets header buffer and body
  603. * buffer and deserializes them into faux_msg_t format.
  604. *
  605. * @param [in] hdr Message header.
  606. * @param [in] body Message body.
  607. * @param [in] body_len Length of message body.
  608. * @return Deserialized faux_msg_t object or NULL on error.
  609. */
  610. faux_msg_t *faux_msg_deserialize_parts(const faux_hdr_t *hdr,
  611. const char *body, size_t body_len)
  612. {
  613. faux_msg_t *msg = NULL;
  614. faux_phdr_t *phdr = NULL;
  615. size_t phdr_whole_len = 0;
  616. size_t params_whole_len = 0;
  617. unsigned int i = 0;
  618. const char *data = NULL;
  619. uint32_t param_num = 0;
  620. msg = faux_msg_allocate();
  621. assert(msg);
  622. if (!msg)
  623. return NULL;
  624. // Replace message header by new one
  625. memcpy(msg->hdr, hdr, sizeof(*hdr));
  626. if (0 == body_len) // Message contains header only
  627. return msg;
  628. // Process message body i.e. parameters
  629. param_num = faux_msg_get_param_num(msg);
  630. if (0 == param_num) { // Something went wrong
  631. faux_msg_free(msg);
  632. return NULL;
  633. }
  634. phdr_whole_len = param_num * sizeof(*phdr);
  635. if (phdr_whole_len > body_len) { // Something went wrong
  636. faux_msg_free(msg);
  637. return NULL;
  638. }
  639. phdr = (faux_phdr_t *)body;
  640. // Find out whole parameters length
  641. for (i = 0; i < param_num; i++)
  642. params_whole_len += faux_phdr_get_len(phdr + i);
  643. if ((phdr_whole_len + params_whole_len) != body_len) { // Something went wrong
  644. faux_msg_free(msg);
  645. return NULL;
  646. }
  647. // Parameters
  648. data = body + phdr_whole_len;
  649. for (i = 0; i < param_num; i++) {
  650. size_t cur_data_len = faux_phdr_get_len(phdr + i);
  651. if (0 == cur_data_len)
  652. continue;
  653. faux_msg_add_param_internal(msg,
  654. faux_phdr_get_type(phdr + i),
  655. data, cur_data_len, BOOL_FALSE);
  656. data += cur_data_len;
  657. }
  658. return msg;
  659. }
  660. /* @brief Deserialized message stored in linear buffer.
  661. *
  662. * Message header and message body can be stored in linear buffer. Function
  663. * deserializes it from network format to faux_msg_t structure.
  664. *
  665. * @param [in] data Message in network format.
  666. * @param [in] len Message length.
  667. * @return Deserialized faux_msg_t object or NULL on error.
  668. */
  669. faux_msg_t *faux_msg_deserialize(const char *data, size_t len)
  670. {
  671. const faux_hdr_t *msg_hdr = (const faux_hdr_t *)data;
  672. const char *msg_body = data + sizeof(*msg_hdr);
  673. size_t msg_body_len = len - sizeof(*msg_hdr);
  674. assert(data);
  675. if (!data)
  676. return NULL;
  677. if (len < sizeof(*msg_hdr))
  678. return NULL;
  679. return faux_msg_deserialize_parts(msg_hdr, msg_body, msg_body_len);
  680. }
  681. /** @brief Receives full message and allocates faux_msg_t object for it.
  682. *
  683. * Function receives message from network using preinitialized faux_net_t object.
  684. * User can specify timeout, signal mask, etc while faux_net_t object creation.
  685. *
  686. * Function can return length less than whole message length in the following
  687. * cases:
  688. * - An error has occured like broken file descriptor.
  689. * - Interrupted by allowed signal (see signal mask).
  690. * - Timeout.
  691. *
  692. * @param [in] faux_net Preinitialized faux_net_t object.
  693. * @param [out] status Status while message receiving. Can be NULL.
  694. * @return Allocated faux_msg_t object. Object contains received message.
  695. */
  696. faux_msg_t *faux_msg_recv(faux_net_t *faux_net)
  697. {
  698. faux_msg_t *msg = NULL;
  699. size_t received = 0;
  700. faux_hdr_t hdr = {};
  701. char *body = NULL;
  702. size_t body_len = 0;
  703. // Receive message header
  704. received = faux_net_recv(faux_net, &hdr, sizeof(hdr));
  705. if (received != sizeof(hdr))
  706. return NULL;
  707. body_len = faux_hdr_len(&hdr) - sizeof(hdr);
  708. body = faux_malloc(body_len);
  709. received = faux_net_recv(faux_net, body, body_len);
  710. if (received != body_len) {
  711. faux_free(body);
  712. return NULL;
  713. }
  714. msg = faux_msg_deserialize_parts(&hdr, body, body_len);
  715. faux_free(body);
  716. #ifdef DEBUG
  717. // Debug
  718. if (msg && faux_msg_debug_flag) {
  719. printf("(i) ");
  720. faux_msg_debug(msg);
  721. }
  722. #endif
  723. return msg;
  724. }
  725. /** @brief Prints message debug info.
  726. *
  727. * Function prints header values and parameters.
  728. *
  729. * @param [in] msg Allocated faux_msg_t object.
  730. */
  731. void faux_msg_debug(const faux_msg_t *msg)
  732. #ifdef DEBUG
  733. {
  734. faux_list_node_t *iter = 0;
  735. // Parameter vars
  736. void *param_data = NULL;
  737. uint16_t param_type = 0;
  738. uint32_t param_len = 0;
  739. assert(msg);
  740. if (!msg)
  741. return;
  742. // Header
  743. printf("%x(%u.%u): c%04x s%08x i%08x p%u l%u |%lub\n",
  744. faux_msg_get_magic(msg),
  745. faux_msg_get_major(msg),
  746. faux_msg_get_minor(msg),
  747. faux_msg_get_cmd(msg),
  748. faux_msg_get_status(msg),
  749. faux_msg_get_req_id(msg),
  750. faux_msg_get_param_num(msg),
  751. faux_msg_get_len(msg),
  752. sizeof(*msg->hdr)
  753. );
  754. // Parameters
  755. iter = faux_msg_init_param_iter(msg);
  756. while (faux_msg_get_param_each(&iter, &param_type, &param_data, &param_len)) {
  757. printf(" t%04x l%u |%lub\n",
  758. param_type,
  759. param_len,
  760. sizeof(faux_phdr_t) + param_len
  761. );
  762. }
  763. }
  764. #else
  765. {
  766. msg = msg; // Happy compiler
  767. }
  768. #endif