sp_var.c 16 KB

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