You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
17 KiB

4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
  1. // This file is under GNU General Public License 3.0
  2. // see LICENSE.txt
  3. // generate message functions
  4. // Copyleft (c) 2017-2019, p≡p foundation
  5. // Written by Volker Birk
  6. include yslt.yml2
  7. tstylesheet {
  8. include standardlib.ysl2
  9. include ./functions.ysl2
  10. template "/" {
  11. apply "protocol", 0, mode=header;
  12. apply "protocol", 0, mode=impl;
  13. }
  14. template "protocol", mode=header
  15. if "fsm[count(state)]" document "generated/{@name}_func.h", "text"
  16. ||
  17. /**
  18. * @file «@name»_func.h
  19. * @brief State storage and retrieval, and associated «@name» message generation and processing, for the «@name» protocol.
  20. * @generated from ../sync/gen_message_func.ysl2
  21. *
  22. * @license GNU General Public License 3.0 - see LICENSE.txt
  23. */
  24. #ifndef «yml:ucase(@name)»_FUNC_H
  25. #define «yml:ucase(@name)»_FUNC_H
  26. #ifdef __cplusplus
  27. extern "C" {
  28. #endif
  29. #include <stdbool.h>
  30. #include "../asn.1/«@name».h"
  31. `` for "func:distinctType(fsm/message/field[not(func:basicType())])" | #include "../asn.1/«@type».h"
  32. /**
  33. * State information and associated stored data for all «@name» state machines
  34. */
  35. struct «@name»_state_s {
  36. /**
  37. * @struct «@name»_state_s::own_«@name»_state_s
  38. * @brief Own state storage.
  39. */
  40. struct own_«@name»_state_s {
  41. stringlist_t *keys; //!< own keys
  42. stringlist_t *backup; //!< ????
  43. identity_list *identities; //!< own identities
  44. `` for "fsm/message[@ratelimit>0]" |>> time_t last_«../@name»_«@name»; //!< Timestamp of last «../@name» «@name» message accepted
  45. // TIDs we're using ourselves
  46. `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»; //!< own «@name» TID
  47. } own; /*!< Own state storage */
  48. /**
  49. * @struct «@name»_state_s::comm_partner_state_s
  50. * @brief State acquired from our communications partner
  51. */
  52. struct comm_partner_state_s {
  53. // transport data we expect
  54. char *sender_fpr; //!< sender fpr for comm partner that we expect all sender messages to be signed by
  55. pEp_identity *identity; //!< comm partner identity
  56. // TIDs our comm partner wants to have
  57. `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»; //!< sender's «@name» TID
  58. } comm_partner; /*!< Received comm partner state storage */
  59. /**
  60. * @struct «@name»_state_s::transport_data_s
  61. * @brief Input buffer for actual transport data coming in
  62. */
  63. struct transport_data_s {
  64. // transport data we got
  65. pEp_identity *from; //!< identity of the sender of incoming transport data
  66. char *sender_fpr; //!< sender fpr for sender of incoming transport data
  67. } transport; /*!< transport input buffer */
  68. `` apply "fsm", mode=state
  69. };
  70. /**
  71. * <!-- free_«@name»_state() -->
  72. *
  73. * @brief free and reset all «@name» state associated with this session
  74. *
  75. * @param[in] session the session
  76. *
  77. */
  78. void free_«@name»_state(PEP_SESSION session);
  79. // functions for protocol «@name»
  80. /**
  81. * <!-- new_«@name»_message() -->
  82. *
  83. * @brief Generate new «@name»_t message structure of the given message type
  84. * for the input finite state machine type
  85. *
  86. * @param[in] fsm current state machine type (??)
  87. * @param[in] message_type the type of «@name» message struct to be created (with empty data)
  88. *
  89. * @return message the message struct desired
  90. * @return NULL if the message_type is unknown
  91. *
  92. * @TODO This description comes entirely from code inspection, but is probably
  93. * better optimised by the author. Caveat lector - I may have gotten it wrong.
  94. */
  95. «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type);
  96. /**
  97. * <!-- free_«@name»_message() -->
  98. *
  99. * @brief free a/an «@name»_t asn.1 message struct
  100. *
  101. * @param[in] msg the «@name»_t message struct to free
  102. *
  103. * @TODO This description comes entirely from code inspection, but is probably
  104. * better optimised by the author. Caveat lector - I may have gotten it wrong.
  105. */
  106. void free_«@name»_message(«@name»_t *msg);
  107. /**
  108. * <!-- update_«@name»_state() -->
  109. *
  110. * @brief Given a/an «@name» message and its corresponding finite state machine,
  111. * update the session's state for its «@name» state machine given the information
  112. * decoded from the message.
  113. *
  114. * This function takes a «@name» message and, depending on the type of «@name» message it is,
  115. * (determined during parsing), copies the relevant data from the message struct into the
  116. * corresponding session state structures as a utf8 string.
  117. *
  118. * @param[in] session session associated with the «@name» finite state machine
  119. * @param[in] msg the message struct containing «@name» data (asn.1 - XER?)
  120. * @param[out] fsm present finite state machine type indicated by the message
  121. * @param[out] message_type the type of the message that was sent in
  122. *
  123. * @retval status
  124. *
  125. * @TODO This description comes entirely from code inspection, but is probably
  126. * better optimised by the author. Caveat lector - I may have gotten it wrong.
  127. *
  128. */
  129. PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
  130. «@name»_PR *fsm, int *message_type);
  131. /**
  132. * <!-- update_«@name»_message() -->
  133. *
  134. * @brief Given a «@name»_t message struct, fill in the relevant data for that message type and
  135. * the state machine type indicated in the message from the current information contained
  136. * in the session according to the message type indicated on the message struct
  137. *
  138. * @param[in] session the session from which to take the «@name» data
  139. * @param[in] msg the «@name»_t message structure
  140. *
  141. * @retval status
  142. *
  143. * @TODO This description comes entirely from code inspection, but is probably
  144. * better optimised by the author. Caveat lector - I may have gotten it wrong.
  145. */
  146. PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg);
  147. #ifdef __cplusplus
  148. }
  149. #endif
  150. #endif
  151. ||
  152. template "fsm", mode=state
  153. ||
  154. /**
  155. * @struct «../@name»::_«@name»_state_s
  156. * @brief Input/output buffer for «@name» messages
  157. *
  158. * @note Can't find a good way to generate documentation for the fields here.
  159. */
  160. struct _«@name»_state_s {
  161. int state; //!< current «@name» state
  162. `` for "func:distinctName(message/field)" |> «func:ctype()» «@name»;
  163. } «yml:lcase(@name)»; /*!< «@name» message Input/output buffer */
  164. ||
  165. template "protocol", mode=impl
  166. if "fsm[count(state)]" document "generated/{@name}_func.c", "text" {
  167. ||
  168. /**
  169. * @file «@name»_func.c
  170. * @brief Implementation of tate storage and retrieval, and associated «@name» message
  171. * generation and processing, for the «@name» protocol.
  172. * @generated from ../sync/gen_message_func.ysl2
  173. *
  174. * @license GNU General Public License 3.0 - see LICENSE.txt
  175. */
  176. #include <assert.h>
  177. #include <stdlib.h>
  178. #include "pEp_internal.h"
  179. #include "map_asn1.h"
  180. #include "«@name»_func.h"
  181. `` for "fsm" | #include "«@name»_fsm.h"
  182. void free_«@name»_state(PEP_SESSION session)
  183. {
  184. if (!session)
  185. return;
  186. // own state
  187. free_stringlist(session->«yml:lcase(@name)»_state.own.keys);
  188. session->«yml:lcase(@name)»_state.own.keys = NULL;
  189. free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
  190. session->«yml:lcase(@name)»_state.own.identities = NULL;
  191. // TIDs we're using ourselves
  192. ||
  193. for "func:distinctName(fsm/message/field[@type='TID'])"
  194. |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.own.«@name»);
  195. ||
  196. // state we learned about our communication partner
  197. free(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
  198. session->«yml:lcase(@name)»_state.comm_partner.sender_fpr = NULL;
  199. free_identity(session->«yml:lcase(@name)»_state.comm_partner.identity);
  200. session->«yml:lcase(@name)»_state.comm_partner.identity = NULL;
  201. // TIDs our comm partner wants to have
  202. ||
  203. for "func:distinctName(fsm/message/field[@type='TID'])"
  204. |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.comm_partner.«@name»);
  205. ||
  206. // buffer for transport data
  207. free_identity(session->«yml:lcase(@name)»_state.transport.from);
  208. session->«yml:lcase(@name)»_state.transport.from = NULL;
  209. free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
  210. session->«yml:lcase(@name)»_state.transport.sender_fpr = NULL;
  211. // message buffers
  212. ||
  213. for "fsm" {
  214. for "func:distinctName(message/field[not(substring(@type,1,1)=yml:lcase(substring(@type,1,1)))])"
  215. |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  216. |
  217. }
  218. ||
  219. memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
  220. }
  221. «@name»_t *new_«@name»_message(«@name»_PR fsm, int message_type)
  222. {
  223. «@name»_t *msg = calloc(sizeof(«@name»_t), 1);
  224. assert(msg);
  225. if (!msg)
  226. return NULL;
  227. if (fsm) {
  228. msg->present = fsm;
  229. if (message_type) {
  230. switch (fsm) {
  231. `` apply "fsm", 4, mode=impl
  232. default:
  233. free(msg);
  234. return NULL;
  235. }
  236. }
  237. }
  238. return msg;
  239. }
  240. void free_«@name»_message(«@name»_t *msg)
  241. {
  242. ASN_STRUCT_FREE(asn_DEF_«@name», msg);
  243. }
  244. PEP_STATUS update_«@name»_state(PEP_SESSION session, «@name»_t *msg,
  245. «@name»_PR *fsm, int *message_type)
  246. {
  247. int result = 0;
  248. assert(session && msg && fsm && message_type);
  249. if (!(session && msg && fsm && message_type))
  250. return PEP_ILLEGAL_VALUE;
  251. *fsm = 0;
  252. *message_type = None;
  253. switch (msg->present) {
  254. case «@name»_PR_NOTHING:
  255. return PEP_ILLEGAL_VALUE;
  256. `` apply "fsm", 2, mode=update_state
  257. default:
  258. return PEP_ILLEGAL_VALUE;
  259. }
  260. *fsm = msg->present;
  261. return PEP_STATUS_OK;
  262. }
  263. PEP_STATUS update_«@name»_message(PEP_SESSION session, «@name»_t *msg)
  264. {
  265. assert(session && msg);
  266. if (!(session && msg))
  267. return PEP_ILLEGAL_VALUE;
  268. int fsm = msg->present;
  269. switch (fsm) {
  270. case «@name»_PR_NOTHING:
  271. return PEP_ILLEGAL_VALUE;
  272. `` apply "fsm", 2, mode=update_message
  273. default:
  274. return PEP_ILLEGAL_VALUE;
  275. }
  276. return PEP_STATUS_OK;
  277. }
  278. ||
  279. }
  280. template "fsm", mode=update_message
  281. ||
  282. case «../@name»_PR_«yml:lcase(@name)»:
  283. {
  284. int message_type = msg->choice.«yml:lcase(@name)».present;
  285. switch (message_type) {
  286. case «@name»_PR_NOTHING:
  287. return PEP_ILLEGAL_VALUE;
  288. `` apply "message", 2, mode=update_message
  289. default:
  290. return PEP_ILLEGAL_VALUE;
  291. }
  292. break;
  293. }
  294. ||
  295. template "message", mode=update_message {
  296. ||
  297. case «../@name»_PR_«yml:mixedCase(@name)»:
  298. `` apply "auto"
  299. `` apply "field", mode=update_message
  300. break;
  301. ||
  302. }
  303. template "auto" choose {
  304. when "@type = 'Version'" {
  305. const "fsm", "ancestor::fsm";
  306. ||
  307. {
  308. long *major = (long *) malloc(sizeof(long));
  309. long *minor = (long *) malloc(sizeof(long));
  310. assert(major && minor);
  311. if (!(major && minor))
  312. return PEP_OUT_OF_MEMORY;
  313. *major = «$fsm/version/@major»;
  314. *minor = «$fsm/version/@minor»;
  315. msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».major = major;
  316. msg->choice.«yml:lcase($fsm/@name)».choice.«yml:mixedCase(../@name)».«@name».minor = minor;
  317. }
  318. ||
  319. }
  320. otherwise
  321. error "unkown type for auto in message: {@type}; allowed types: Version";
  322. }
  323. template "field", mode=update_message {
  324. const "message_name", "yml:mixedCase(../@name)";
  325. const "state" > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
  326. choose {
  327. when "func:basicType() or @type='Rating'" // copyable
  328. ||
  329. msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»
  330. = session->«$state».«@name»;
  331. ||
  332. when "@type='Identity'"
  333. ||
  334. {
  335. pEp_identity *ident = Identity_to_Struct(&session->«$state».«@name», NULL);
  336. if (!ident)
  337. return PEP_OUT_OF_MEMORY;
  338. Identity_t *_ident = Identity_from_Struct(ident,
  339. &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
  340. free_identity(ident);
  341. if (!_ident)
  342. return PEP_OUT_OF_MEMORY;
  343. }
  344. ||
  345. when "@type='IdentityList'"
  346. ||
  347. {
  348. identity_list *il = IdentityList_to_identity_list(
  349. &session->«$state».«@name», NULL);
  350. if (!il)
  351. return PEP_OUT_OF_MEMORY;
  352. PEP_STATUS own_idents_status = set_all_userids_to_own(session, il);
  353. if (own_idents_status != PEP_STATUS_OK)
  354. return own_idents_status;
  355. IdentityList_t *_il = IdentityList_from_identity_list(il,
  356. &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
  357. free_identity_list(il);
  358. if (!_il)
  359. return PEP_OUT_OF_MEMORY;
  360. }
  361. ||
  362. otherwise // string based
  363. ||
  364. {
  365. int result = OCTET_STRING_fromBuf(
  366. &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»,
  367. (char *) session->«$state».«@name».buf,
  368. session->«$state».«@name».size
  369. );
  370. if (result)
  371. return PEP_OUT_OF_MEMORY;
  372. }
  373. ||
  374. }
  375. }
  376. template "fsm", mode=update_state
  377. ||
  378. case «../@name»_PR_«yml:lcase(@name)»:
  379. switch (msg->choice.«yml:lcase(@name)».present) {
  380. case «@name»_PR_NOTHING:
  381. return PEP_ILLEGAL_VALUE;
  382. `` apply "message", 2, mode=update_state
  383. default:
  384. return PEP_ILLEGAL_VALUE;
  385. }
  386. break;
  387. ||
  388. template "message", mode=update_state {
  389. const "message_name", "concat(yml:lcase(substring(@name,1,1)), substring(@name,2))";
  390. ||
  391. case «../@name»_PR_«$message_name»:
  392. `` apply "field", mode=update_state with "message_name", "$message_name"
  393. *message_type = «yml:capit($message_name)»;
  394. break;
  395. ||
  396. }
  397. template "field", mode=update_state {
  398. param "message_name";
  399. choose {
  400. when "func:basicType() or @type='Rating'" // copyable
  401. ||
  402. session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name» = msg->choice.«yml:lcase(../../@name)»
  403. .choice.«$message_name».«@name»;
  404. ||
  405. when "@type='Identity'"
  406. ||
  407. {
  408. pEp_identity *ident = Identity_to_Struct(
  409. &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
  410. if (!ident)
  411. return PEP_OUT_OF_MEMORY;
  412. Identity_t *_ident = Identity_from_Struct(ident,
  413. &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  414. free_identity(ident);
  415. if (!_ident)
  416. return PEP_OUT_OF_MEMORY;
  417. }
  418. ||
  419. when "@type='IdentityList'"
  420. ||
  421. {
  422. identity_list *il = IdentityList_to_identity_list(
  423. &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
  424. if (!il)
  425. return PEP_OUT_OF_MEMORY;
  426. PEP_STATUS own_idents_status = set_all_userids_to_own(session, il);
  427. if (own_idents_status != PEP_STATUS_OK)
  428. return own_idents_status;
  429. IdentityList_t *_il = IdentityList_from_identity_list(il,
  430. &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  431. free_identity_list(il);
  432. if (!_il)
  433. return PEP_OUT_OF_MEMORY;
  434. }
  435. ||
  436. otherwise // string based
  437. ||
  438. result = OCTET_STRING_fromBuf(&session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»,
  439. (char *) msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».buf,
  440. msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name».size);
  441. if (result)
  442. return PEP_OUT_OF_MEMORY;
  443. ||
  444. }
  445. }
  446. template "fsm", mode=impl
  447. ||
  448. case «../@name»_PR_«yml:lcase(@name)»:
  449. msg->choice.«yml:lcase(@name)».present = message_type;
  450. break;
  451. ||
  452. }