sp_var.c 16 KB

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