sp_var.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. #include "precompile.h"
  2. #include "sp_var.h"
  3. #include "sp_def.h"
  4. #include "sp_svc.h"
  5. #include "sp_dbg_export.h"
  6. #include "sp_iom.h"
  7. #include "sp_cfg.h"
  8. #include "sp_env.h"
  9. #include "sp_rsn.h"
  10. #include "memutil.h"
  11. #include "array.h"
  12. #include "refcnt.h"
  13. #include "iniutil.h"
  14. #include <winpr/synch.h>
  15. #include <winpr/string.h>
  16. #define VAR_CMD_CHANGE 0x01
  17. #define VAR_CMD_SUBSCRIBE 0x02
  18. #define VAR_CMD_UNSUBSCRIBE 0x03
  19. struct sp_var_client_t
  20. {
  21. sp_svc_t *svc;
  22. };
  23. static int sp_var_can_write(sp_var_client_t *client, const char *key, sp_cfg_shell_sysevent_t **p_sysevent)
  24. {
  25. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  26. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  27. sp_cfg_shell_sysevent_t *sysevent;
  28. sysevent = sp_cfg_get_sysevent(cfg, key);
  29. if (sysevent) {
  30. int i;
  31. *p_sysevent = sysevent;
  32. for (i = 0; i < sysevent->arr_owner_entity->nelts; ++i) {
  33. sp_cfg_shell_entity_t *ent = ARRAY_IDX(sysevent->arr_owner_entity, i, sp_cfg_shell_entity_t*);
  34. if (ent->idx == sp_svc_get_id(client->svc))
  35. return TRUE;
  36. }
  37. } else {
  38. *p_sysevent = NULL;
  39. }
  40. return FALSE;
  41. }
  42. int sp_var_client_create(sp_svc_t *svc, sp_var_client_t **p_client)
  43. {
  44. sp_var_client_t *client = MALLOC_T(sp_var_client_t);
  45. client->svc = svc;
  46. *p_client = client;
  47. return 0;
  48. }
  49. void sp_var_client_destroy(sp_var_client_t *client)
  50. {
  51. free(client);
  52. }
  53. // str == NULL for delete
  54. int sp_var_client_set(sp_var_client_t *client, const char *key, const char *str, int persist)
  55. {
  56. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  57. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  58. int svc_id = sp_svc_get_id(client->svc);
  59. int rc;
  60. sp_cfg_shell_sysevent_t *sysevent;
  61. char old_value[SP_CFG_MAX_SYSEVT_BUF];
  62. if (!key ) {
  63. sp_dbg_warn("%s invalid argument", __FUNCTION__);
  64. return Error_Null;
  65. }
  66. if (str && strlen(str) >= SP_CFG_MAX_SYSEVT_BUF) {
  67. sp_dbg_warn("%s has exceed max sysevent length!", key);
  68. return Error_Overflow;
  69. }
  70. if (!sp_var_can_write(client, key, &sysevent)) {
  71. if (sysevent == NULL) {
  72. sp_dbg_warn("sys key %s is not existed!", key);
  73. return Error_NotExist;
  74. }
  75. else {
  76. sp_dbg_warn("%s has no write privilege!", __FUNCTION__);
  77. return Error_NoPrivilege;
  78. }
  79. }
  80. // same value, not trigger change event
  81. if ((str != NULL && strcmp(str, sysevent->init_value) == 0)
  82. || (str == NULL && sysevent->init_value[0] == 0)) {
  83. sp_dbg_warn("key previous value is same as current one, ignore it!");
  84. return Error_Succeed;
  85. }
  86. sp_cfg_lock(cfg);
  87. if (str) {
  88. strcpy(old_value, sysevent->init_value);
  89. strcpy(sysevent->init_value, str);
  90. if (persist)
  91. inifile_format_write(cfg->shellvar_ini_path != NULL ? cfg->shellvar_ini_path : cfg->shell_ini_path,
  92. "SysEvent", key, "%s,\"%s\"", sp_cfg_get_entity_by_idx(cfg, svc_id)->name, str);
  93. } else {
  94. sysevent->init_value[0] = 0;
  95. if (persist)
  96. inifile_format_write(cfg->shellvar_ini_path != NULL ? cfg->shellvar_ini_path : cfg->shell_ini_path,
  97. "SysEvent", key, "%s,\"\"", sp_cfg_get_entity_by_idx(cfg, svc_id)->name);
  98. }
  99. sp_cfg_unlock(cfg);
  100. {
  101. iobuffer_t *pkt = iobuffer_create(-1, -1);
  102. iobuffer_write(pkt, IOBUF_T_I4, &svc_id, 0);
  103. iobuffer_write(pkt, IOBUF_T_STR, key, -1);
  104. iobuffer_write(pkt, IOBUF_T_STR, old_value, -1);
  105. iobuffer_write(pkt, IOBUF_T_STR, str, -1);
  106. rc = sp_svc_post(client->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID, SP_PKT_VAR|VAR_CMD_CHANGE, 0, &pkt);
  107. if (rc != 0) {
  108. sp_dbg_warn("%s post SP_PKT_VAR|VAR_CMD_CHANGE failed!", __FUNCTION__);
  109. }
  110. if (pkt)
  111. iobuffer_dec_ref(pkt);
  112. }
  113. return rc;
  114. }
  115. int sp_var_client_get(sp_var_client_t *client, const char *key, char *str, int *n)
  116. {
  117. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  118. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  119. int rc = 0;
  120. sp_cfg_shell_sysevent_t *sysevent;
  121. sysevent = sp_cfg_get_sysevent(cfg, key);
  122. if (!sysevent) {
  123. sp_dbg_warn("%s cannot find sysevent !", key);
  124. return Error_NotExist;
  125. }
  126. assert(n);
  127. if (str) {
  128. int slen;
  129. sp_cfg_lock(cfg);
  130. slen = (int)strlen(sysevent->init_value);
  131. if (*n > slen) {
  132. strcpy(str, sysevent->init_value);
  133. } else {
  134. *n = slen + 1 > SP_CFG_MAX_SYSEVT_BUF ? SP_CFG_MAX_SYSEVT_BUF : slen + 1;
  135. rc = Error_TooSmallBuffer;
  136. }
  137. sp_cfg_unlock(cfg);
  138. } else {
  139. if (n) {
  140. int slen;
  141. sp_cfg_lock(cfg);
  142. slen = (int)strlen(sysevent->init_value);
  143. sp_cfg_unlock(cfg);
  144. *n = slen + 1 > SP_CFG_MAX_SYSEVT_BUF ? SP_CFG_MAX_SYSEVT_BUF : slen + 1;
  145. rc = Error_TooSmallBuffer;
  146. } else {
  147. rc = Error_Param;
  148. }
  149. }
  150. return rc;
  151. }
  152. int sp_var_client_lock(sp_var_client_t *client)
  153. {
  154. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  155. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  156. sp_cfg_lock(cfg);
  157. return 0;
  158. }
  159. int sp_var_client_unlock(sp_var_client_t *client)
  160. {
  161. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  162. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  163. sp_cfg_unlock(cfg);
  164. return 0;
  165. }
  166. struct sp_var_listener_t
  167. {
  168. int client_id;
  169. int subcribed;
  170. int enabled;
  171. char *key;
  172. strand_t *strand;
  173. sp_var_on_change on_change;
  174. void *user_data;
  175. void *tag;
  176. sp_svc_t *svc;
  177. DECLARE_REF_COUNT_MEMBER(ref_cnt);
  178. };
  179. DECLARE_REF_COUNT_STATIC(sp_var_listener, sp_var_listener_t)
  180. static void listener_on_pkt_threadpool(threadpool_t *threadpool, void *arg)
  181. {
  182. iobuffer_t *pkt = (iobuffer_t*)arg;
  183. sp_var_listener_t *listener;
  184. sp_svc_t *svc;
  185. int epid;
  186. int pkt_type;
  187. int svc_id;
  188. int pkt_id;
  189. sp_uid_t rsn;
  190. sp_rsn_context_t rsn_ctx;
  191. iobuffer_read(pkt, IOBUF_T_PTR, &listener, NULL);
  192. iobuffer_read(pkt, IOBUF_T_I4, &epid, NULL);
  193. iobuffer_read(pkt, IOBUF_T_I4, &svc_id, NULL);
  194. iobuffer_read(pkt, IOBUF_T_I4, &pkt_type, NULL);
  195. iobuffer_read(pkt, IOBUF_T_I4, &pkt_id, NULL);
  196. svc = listener->svc;
  197. rsn = sp_svc_new_runserial(svc);
  198. sp_rsn_context_init_original(rsn, SP_ORIGINAL_T_CALLBACK, &rsn_ctx);
  199. sp_svc_push_runserial_context(svc, &rsn_ctx);
  200. if (listener->subcribed && listener->enabled) {
  201. int var_client_id = pkt_id;
  202. int var_cmd = SP_GET_TYPE(pkt_type);
  203. if (var_cmd == VAR_CMD_CHANGE && listener->subcribed) {
  204. int from_client_id;
  205. char *key = NULL;
  206. iobuffer_format_read(pkt, "4s", &from_client_id, &key);
  207. if ((listener->key[0] == '*' &&_stricmp(key, VAR_RSERVERD_KEY_TERM_STATE) != 0) || _stricmp(key, listener->key) == 0) {
  208. char *old_value = NULL;
  209. char *new_value = NULL;
  210. iobuffer_format_read(pkt, "ss", &old_value, &new_value);
  211. listener->on_change(listener, key, old_value, new_value, from_client_id, listener->user_data);
  212. if (old_value)
  213. toolkit_free(old_value);
  214. if (new_value)
  215. toolkit_free(new_value);
  216. }
  217. if (key)
  218. toolkit_free(key);
  219. }
  220. }
  221. if (pkt)
  222. iobuffer_dec_ref(pkt);
  223. sp_dbg_debug("%s: dec ref", __FUNCTION__);
  224. sp_var_listener_dec_ref(listener); //@
  225. sp_svc_pop_runserial_context(svc);
  226. }
  227. static int listener_on_pkt(sp_svc_t *svc,int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt, void *user_data)
  228. {
  229. sp_var_listener_t *listener = (sp_var_listener_t *)user_data;
  230. int var_cmd = SP_GET_TYPE(pkt_type);
  231. if (var_cmd == VAR_CMD_CHANGE && listener->subcribed && listener->enabled) {
  232. iobuffer_t *pkt = iobuffer_clone(*p_pkt);
  233. iobuffer_write_head(pkt, IOBUF_T_I4, &pkt_id, 0);
  234. iobuffer_write_head(pkt, IOBUF_T_I4, &pkt_type, 0);
  235. iobuffer_write_head(pkt, IOBUF_T_I4, &svc_id, 0);
  236. iobuffer_write_head(pkt, IOBUF_T_I4, &epid, 0);
  237. iobuffer_write_head(pkt, IOBUF_T_PTR, &listener, 0);
  238. sp_dbg_debug("%s: inc ref", __FUNCTION__);
  239. sp_var_listener_inc_ref(listener);//@
  240. if (threadpool_queue_workitem(sp_svc_get_threadpool(svc), listener->strand, &listener_on_pkt_threadpool, pkt) < 0) {
  241. sp_dbg_debug("%s: dec ref", __FUNCTION__);
  242. sp_var_listener_dec_ref(listener);//@
  243. iobuffer_dec_ref(pkt);
  244. }
  245. }
  246. return TRUE; // continue
  247. }
  248. int sp_var_listener_create(sp_svc_t *svc, const char *key, sp_var_on_change on_change, void *user_data, sp_var_listener_t **p_listener)
  249. {
  250. sp_var_listener_t *listener = MALLOC_T(sp_var_listener_t);
  251. listener->on_change = on_change;
  252. listener->user_data = user_data;
  253. listener->subcribed = 0;
  254. listener->enabled = 1;
  255. listener->strand = strand_create();
  256. listener->key = _strdup(key);
  257. listener->svc = svc;
  258. REF_COUNT_INIT(&listener->ref_cnt); // BugFix for @ [Gifur@202051]
  259. *p_listener = listener;
  260. sp_dbg_debug("create listener %llu for key %s (%u)." , listener, listener->key, (void*)listener->key);
  261. return 0;
  262. }
  263. static void __sp_var_listener_destroy(sp_var_listener_t *listener)
  264. {
  265. strand_destroy(listener->strand);
  266. sp_dbg_debug("free listener %llu for key %s (%u).", listener, listener->key, (void*)listener->key);
  267. free(listener->key);
  268. free(listener);
  269. }
  270. IMPLEMENT_REF_COUNT_MT_STATIC(sp_var_listener, sp_var_listener_t, ref_cnt, __sp_var_listener_destroy)
  271. void sp_var_listener_destroy(sp_var_listener_t *listener)
  272. {
  273. sp_dbg_debug("%s: dec ref", __FUNCTION__);
  274. sp_var_listener_dec_ref(listener);
  275. }
  276. int sp_var_listener_subscribe(sp_var_listener_t *listener)
  277. {
  278. iobuffer_t *pkt;
  279. int rc;
  280. if (listener->subcribed)
  281. return Error_Duplication;
  282. pkt = iobuffer_create(-1, -1);
  283. //TODO: int is dangerous.
  284. sp_svc_add_pkt_handler(listener->svc, (int)listener, SP_PKT_VAR, &listener_on_pkt, listener);
  285. iobuffer_write(pkt, IOBUF_T_STR, listener->key, -1);
  286. rc = sp_svc_post(listener->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID,
  287. SP_PKT_VAR|VAR_CMD_SUBSCRIBE, 0, &pkt);
  288. if (rc == 0) {
  289. listener->subcribed = 1;
  290. }
  291. if (pkt)
  292. iobuffer_dec_ref(pkt);
  293. return rc;
  294. }
  295. int sp_var_listener_unsubscribe(sp_var_listener_t *listener)
  296. {
  297. int rc;
  298. if (listener->subcribed) {
  299. iobuffer_t *pkt = iobuffer_create(-1, -1);
  300. iobuffer_write(pkt, IOBUF_T_STR, listener->key, -1);
  301. rc = sp_svc_post(listener->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID,
  302. SP_PKT_VAR|VAR_CMD_UNSUBSCRIBE, 0, &pkt);
  303. if (rc == 0) {
  304. listener->subcribed = 0;
  305. sp_svc_remove_pkt_handler(listener->svc, (int)listener, SP_PKT_VAR);
  306. }
  307. if (pkt)
  308. iobuffer_dec_ref(pkt);
  309. } else {
  310. rc = Error_NotInit;
  311. }
  312. return rc;
  313. }
  314. void sp_var_listener_set_tag(sp_var_listener_t *listener, void *tag)
  315. {
  316. listener->tag = tag;
  317. }
  318. void* sp_var_listener_get_tag(sp_var_listener_t *listener)
  319. {
  320. return listener->tag;
  321. }
  322. int sp_var_listener_enable(sp_var_listener_t *listener, int enabled)
  323. {
  324. int old = listener->enabled;
  325. listener->enabled = enabled;
  326. return old;
  327. }
  328. typedef struct var_listener_entry {
  329. int epid;
  330. int svc_id;
  331. char *key;
  332. int instance;
  333. }var_listener_entry;
  334. struct sp_var_daemon_t
  335. {
  336. CRITICAL_SECTION lock;
  337. array_header_t *arr_listener;
  338. sp_svc_t *svc;
  339. };
  340. static void daemon_lock(sp_var_daemon_t *daemon)
  341. {
  342. EnterCriticalSection(&daemon->lock);
  343. }
  344. static void daemon_unlock(sp_var_daemon_t *daemon)
  345. {
  346. LeaveCriticalSection(&daemon->lock);
  347. }
  348. static int daemon_on_pkt(sp_svc_t *svc,int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt, void *user_data)
  349. {
  350. sp_var_daemon_t *daemon = (sp_var_daemon_t *)user_data;
  351. int var_cmd = SP_GET_TYPE(pkt_type);
  352. if (var_cmd == VAR_CMD_CHANGE) {
  353. iobuffer_t *pkt = *p_pkt;
  354. int i;
  355. int client_id;
  356. int read_state = iobuffer_get_read_state(pkt);
  357. int write_state = iobuffer_get_write_state(pkt);
  358. char *key = NULL;
  359. iobuffer_format_read(pkt, "4s", &client_id, &key);
  360. iobuffer_restore_read_state(pkt, read_state);
  361. iobuffer_restore_write_state(pkt, write_state);
  362. daemon_lock(daemon);
  363. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  364. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  365. if ((_stricmp(tmp->key, "*") == 0 && _stricmp(key, VAR_RSERVERD_KEY_TERM_STATE) !=0)
  366. || _stricmp(key, tmp->key) == 0) {
  367. iobuffer_t *copy_pkt;
  368. if (i == daemon->arr_listener->nelts-1) {
  369. copy_pkt = pkt;
  370. pkt =NULL;
  371. } else {
  372. copy_pkt = iobuffer_clone(pkt);
  373. }
  374. sp_svc_post(daemon->svc, tmp->epid, tmp->svc_id, SP_PKT_VAR|VAR_CMD_CHANGE, 0, &copy_pkt);
  375. if (copy_pkt)
  376. iobuffer_dec_ref(copy_pkt);
  377. }
  378. }
  379. daemon_unlock(daemon);
  380. toolkit_free(key);
  381. if (pkt)
  382. iobuffer_dec_ref(pkt);
  383. *p_pkt = NULL;
  384. } else if (var_cmd == VAR_CMD_SUBSCRIBE) {
  385. char *key = NULL;
  386. int i;
  387. int slen;
  388. iobuffer_read(*p_pkt, IOBUF_T_STR, NULL, &slen);
  389. key = malloc(slen+1);
  390. iobuffer_read(*p_pkt, IOBUF_T_STR, key, NULL);
  391. daemon_lock(daemon);
  392. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  393. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  394. if (tmp->epid == epid && tmp->svc_id == svc_id && _stricmp(key, tmp->key) == 0) {
  395. tmp->instance++;
  396. break;
  397. }
  398. }
  399. if (i == daemon->arr_listener->nelts) {
  400. var_listener_entry* tmp = MALLOC_T(var_listener_entry);
  401. tmp->epid = epid;
  402. tmp->svc_id = svc_id;
  403. tmp->key = key;
  404. key = NULL;
  405. tmp->instance = 1;
  406. ARRAY_PUSH(daemon->arr_listener, var_listener_entry*) = tmp;
  407. }
  408. daemon_unlock(daemon);
  409. if (key)
  410. free(key);
  411. } else if (var_cmd == VAR_CMD_UNSUBSCRIBE) {
  412. char *key = NULL;
  413. int i;
  414. int slen;
  415. iobuffer_read(*p_pkt, IOBUF_T_STR, NULL, &slen);
  416. key = malloc(slen+1);
  417. iobuffer_read(*p_pkt, IOBUF_T_STR, key, NULL);
  418. daemon_lock(daemon);
  419. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  420. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  421. if (tmp->epid == epid && tmp->svc_id == svc_id && _stricmp(key, tmp->key) == 0) {
  422. tmp->instance--;
  423. if (tmp->instance == 0) {
  424. if (i < daemon->arr_listener->nelts-1)
  425. ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*) = ARRAY_IDX(daemon->arr_listener, daemon->arr_listener->nelts-1, var_listener_entry*);
  426. array_pop(daemon->arr_listener);
  427. free(tmp->key);
  428. free(tmp);
  429. }
  430. break;
  431. }
  432. }
  433. daemon_unlock(daemon);
  434. if (key)
  435. free(key);
  436. } else {
  437. assert(0);
  438. }
  439. return TRUE;
  440. }
  441. static void daemon_on_sys(sp_svc_t *svc,int epid, int state, void *user_data)
  442. {
  443. sp_var_daemon_t *daemon = (sp_var_daemon_t *)user_data;
  444. if (state == BUS_STATE_OFF) {
  445. int i = 0;
  446. daemon_lock(daemon);
  447. while (i < daemon->arr_listener->nelts) {
  448. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  449. if (tmp->epid == epid) {
  450. if (i < daemon->arr_listener->nelts-1)
  451. ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*) = ARRAY_IDX(daemon->arr_listener, daemon->arr_listener->nelts-1, var_listener_entry*);
  452. array_pop(daemon->arr_listener);
  453. free(tmp->key);
  454. free(tmp);
  455. } else {
  456. ++i;
  457. }
  458. }
  459. daemon_unlock(daemon);
  460. }
  461. }
  462. int sp_var_daemon_create(sp_svc_t *svc, sp_var_daemon_t **p_daemon)
  463. {
  464. sp_var_daemon_t *daemon = ZALLOC_T(sp_var_daemon_t);
  465. daemon->svc = svc;
  466. daemon->arr_listener = array_make(3, sizeof(var_listener_entry*));
  467. InitializeCriticalSection(&daemon->lock);
  468. sp_svc_add_pkt_handler(svc, (int)daemon, SP_PKT_VAR, &daemon_on_pkt, daemon);
  469. sp_svc_add_sys_handler(svc, (int)daemon, &daemon_on_sys, daemon);
  470. *p_daemon = daemon;
  471. return 0;
  472. }
  473. void sp_var_daemon_destroy(sp_var_daemon_t *daemon)
  474. {
  475. int i;
  476. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  477. var_listener_entry *tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  478. free(tmp->key);
  479. free(tmp);
  480. }
  481. array_free(daemon->arr_listener);
  482. DeleteCriticalSection(&daemon->lock);
  483. sp_svc_remove_pkt_handler(daemon->svc, (int)daemon, SP_PKT_VAR);
  484. sp_svc_remove_sys_handler(daemon->svc, (int)daemon);
  485. free(daemon);
  486. }