From Diminutive Wolf, 7 Years ago, written in Plain Text.
- go back
Embed
Viewing differences between and Untitled
  1. diff --git a/libs/libblade/src/blade_connection.c b/libs/libblade/src/blade_connection.c
  2. new file mode 100644
  3. index 0000000..cebc027
  4. --- /dev/null
  5. +++ b/libs/libblade/src/blade_connection.c
  6. @@ -0,0 +1,209 @@
  7. +/*
  8. + * Copyright (c) 2017, Shane Bryldt
  9. + * All rights reserved.
  10. + *
  11. + * Redistribution and use in source and binary forms, with or without
  12. + * modification, are permitted provided that the following conditions
  13. + * are met:
  14. + *
  15. + * * Redistributions of source code must retain the above copyright
  16. + * notice, this list of conditions and the following disclaimer.
  17. + *
  18. + * * Redistributions in binary form must reproduce the above copyright
  19. + * notice, this list of conditions and the following disclaimer in the
  20. + * documentation and/or other materials provided with the distribution.
  21. + *
  22. + * * Neither the name of the original author; nor the names of any contributors
  23. + * may be used to endorse or promote products derived from this software
  24. + * without specific prior written permission.
  25. + *
  26. + *
  27. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  30. + * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  32. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  33. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  34. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. + */
  39. +
  40. +#include "blade.h"
  41. +
  42. +struct blade_connection_s {
  43. +       blade_handle_t *handle;
  44. +       ks_pool_t *pool;
  45. +
  46. +       void *transport_data;
  47. +       blade_transport_callbacks_t *transport_callbacks;
  48. +
  49. +       ks_bool_t shutdown;
  50. +    ks_thread_t *state_thread;
  51. +       blade_connection_state_t state;
  52. +      
  53. +       ks_q_t *sending;
  54. +       ks_q_t *receiving;
  55. +};
  56. +
  57. +void *blade_connection_state_thread(ks_thread_t *thread, void *data);
  58. +
  59. +
  60. +KS_DECLARE(ks_status_t) blade_connection_create(blade_connection_t **bcP,
  61. +                                                                                               blade_handle_t *bh,
  62. +                                                                                               void *transport_data,
  63. +                                                                                               blade_transport_callbacks_t *transport_callbacks)
  64. +{
  65. +       blade_connection_t *bc = NULL;
  66. +       ks_pool_t *pool = NULL;
  67. +
  68. +       ks_assert(bcP);
  69. +       ks_assert(bh);
  70. +       ks_assert(transport_data);
  71. +       ks_assert(transport_callbacks);
  72. +
  73. +       pool = blade_handle_pool_get(bh);
  74. +
  75. +       bc = ks_pool_alloc(pool, sizeof(blade_connection_t));
  76. +       bc->handle = bh;
  77. +       bc->pool = pool;
  78. +       bc->transport_data = transport_data;
  79. +       bc->transport_callbacks = transport_callbacks;
  80. +       bc->state = BLADE_CONNECTION_STATE_NONE;
  81. +       ks_q_create(&bp->sending, pool, 0);
  82. +       ks_q_create(&bp->receiving, pool, 0);
  83. +       *bcP = bc;
  84. +
  85. +       return KS_STATUS_SUCCESS;
  86. +}
  87. +
  88. +KS_DECLARE(ks_status_t) blade_connection_destroy(blade_connection_t **bcP)
  89. +{
  90. +       blade_connection_t *bc = NULL;
  91. +      
  92. +       ks_assert(bcP);
  93. +       ks_assert(*bcP);
  94. +
  95. +       bc = *bcP;
  96. +
  97. +       blade_connection_shutdown(bc);
  98. +
  99. +       ks_q_destroy(&bc->sending);
  100. +       ks_q_destroy(&bc->receiving);
  101. +
  102. +       ks_pool_free(bc->pool, bcP);
  103. +
  104. +       return KS_STATUS_SUCCESS;
  105. +}
  106. +
  107. +KS_DECLARE(ks_status_t) blade_connection_startup(blade_connection_t *bc)
  108. +{
  109. +       ks_assert(bc);
  110. +
  111. +       bc->state = BLADE_CONNECTION_STATE_NONE;
  112. +
  113. +    if (ks_thread_create_ex(&bc->state_thread,
  114. +                                                       blade_connection_state_thread,
  115. +                                                       bc,
  116. +                                                       KS_THREAD_FLAG_DEFAULT,
  117. +                                                       KS_THREAD_DEFAULT_STACK,
  118. +                                                       KS_PRI_NORMAL,
  119. +                                                       bc->pool) != KS_STATUS_SUCCESS) {
  120. +               // @todo error logging
  121. +               blade_connection_disconnect(bc);
  122. +               return KS_STATUS_FAIL;
  123. +       }
  124. +      
  125. +       return KS_STATUS_SUCCESS;
  126. +}
  127. +
  128. +KS_DECLARE(ks_status_t) blade_connection_shutdown(blade_connection_t *bc)
  129. +{
  130. +       ks_assert(bc);
  131. +
  132. +       if (bc->state_thread) {
  133. +               bc->shutdown = KS_TRUE;
  134. +               ks_thread_join(bp->kws_thread);
  135. +               ks_pool_free(bp->pool, &bp->kws_thread);
  136. +               bc->shutdown = KS_FALSE;
  137. +       }
  138. +
  139. +       //while (ks_q_trypop(bc->sending, (void **)&message) == KS_STATUS_SUCCESS && message) blade_message_discard(&message);
  140. +       //while (ks_q_trypop(bc->receiving, (void **)&message) == KS_STATUS_SUCCESS && message) blade_message_discard(&message);
  141. +
  142. +       return KS_STATUS_SUCCESS;
  143. +}
  144. +
  145. +KS_DECLARE(void) blade_connection_disconnect(blade_connection_t *bc)
  146. +{
  147. +       ks_assert(bc);
  148. +
  149. +       bc->state = BLADE_CONNECTION_STATE_DISCONNECT;
  150. +}
  151. +
  152. +KS_DECLARE(void *) blade_connection_transport_get(blade_connection_t *bc)
  153. +{
  154. +       ks_assert(bc);
  155. +
  156. +       return bc->transport_data;
  157. +}
  158. +
  159. +KS_DECLARE(blade_connection_state_t) blade_connection_state_get(blade_connection_t *bc)
  160. +{
  161. +       ks_assert(bc);
  162. +
  163. +       return bc->state;
  164. +}
  165. +
  166. +KS_DECLARE(void) blade_connection_state_set(blade_connection_t *bc, blade_connection_state_t state)
  167. +{
  168. +       ks_assert(bc);
  169. +
  170. +       bc->state = state;
  171. +}
  172. +
  173. +KS_DECLARE(ks_status_t) blade_connection_sending_push(blade_connection_t *bc, blade_identity_t *target, cJSON *json)
  174. +{
  175. +       ks_assert(bc);
  176. +       ks_assert(json);
  177. +
  178. +       return KS_STATUS_SUCCESS;
  179. +}
  180. +
  181. +KS_DECLARE(ks_status_t) blade_connection_sending_pop(blade_connection_t *bc, blade_identity_t **target, cJSON **json)
  182. +{
  183. +       ks_assert(bc);
  184. +       ks_assert(json);
  185. +
  186. +       return KS_STATUS_SUCCESS;
  187. +}
  188. +
  189. +void *blade_connection_state_thread(ks_thread_t *thread, void *data)
  190. +{
  191. +       blade_connection_t *bc = NULL;
  192. +
  193. +       ks_assert(thread);
  194. +       ks_assert(data);
  195. +
  196. +       bc = (blade_connection_t *)data;
  197. +
  198. +       while (!bc->shutdown) {
  199. +               if (bc->transport_callbacks->onpulse(bc) != KS_STATUS_SUCCESS)
  200. +                       blade_connection_disconnect(bc);
  201. +       }
  202. +
  203. +       return NULL;
  204. +}
  205. +      
  206. +/* For Emacs:
  207. + * Local Variables:
  208. + * mode:c
  209. + * indent-tabs-mode:t
  210. + * tab-width:4
  211. + * c-basic-offset:4
  212. + * End:
  213. + * For VIM:
  214. + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  215. + */
  216. diff --git a/libs/libblade/src/blade_module.c b/libs/libblade/src/blade_module.c
  217. new file mode 100644
  218. index 0000000..414e895
  219. --- /dev/null
  220. +++ b/libs/libblade/src/blade_module.c
  221. @@ -0,0 +1,96 @@
  222. +/*
  223. + * Copyright (c) 2017, Shane Bryldt
  224. + * All rights reserved.
  225. + *
  226. + * Redistribution and use in source and binary forms, with or without
  227. + * modification, are permitted provided that the following conditions
  228. + * are met:
  229. + *
  230. + * * Redistributions of source code must retain the above copyright
  231. + * notice, this list of conditions and the following disclaimer.
  232. + *
  233. + * * Redistributions in binary form must reproduce the above copyright
  234. + * notice, this list of conditions and the following disclaimer in the
  235. + * documentation and/or other materials provided with the distribution.
  236. + *
  237. + * * Neither the name of the original author; nor the names of any contributors
  238. + * may be used to endorse or promote products derived from this software
  239. + * without specific prior written permission.
  240. + *
  241. + *
  242. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  243. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  244. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  245. + * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  246. + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  247. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  248. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  249. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  250. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  251. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  252. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  253. + */
  254. +
  255. +#include "blade.h"
  256. +
  257. +struct blade_module_s {
  258. +       blade_handle_t *handle;
  259. +       ks_pool_t *pool;
  260. +
  261. +       void *module_data;
  262. +       blade_module_callbacks_t *module_callbacks;
  263. +};
  264. +
  265. +
  266. +KS_DECLARE(ks_status_t) blade_module_create(blade_module_t **bmP, blade_handle_t *bh, void *module_data, blade_module_callbacks_t *module_callbacks)
  267. +{
  268. +       blade_module_t *bm = NULL;
  269. +       ks_pool_t *pool = NULL;
  270. +
  271. +       ks_assert(bmP);
  272. +       ks_assert(handle);
  273. +       ks_assert(module_data);
  274. +       ks_assert(module_callbacks);
  275. +
  276. +       pool = blade_handle_pool_get(bh);
  277. +
  278. +       bm = ks_pool_alloc(pool, sizeof(blade_module_t));
  279. +       bm->handle = bh;
  280. +       bm->pool = pool;
  281. +       bm->module_data = module_data;
  282. +       bm->module_callbacks = module_callbacks;
  283. +       *bmP = bm;
  284. +
  285. +       return KS_STATUS_SUCCESS;
  286. +}
  287. +
  288. +KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP)
  289. +{
  290. +       ks_assert(bmP);
  291. +
  292. +       ks_pool_free(bm->pool, bmP);
  293. +
  294. +       return KS_STATUS_SUCCESS;
  295. +}
  296. +
  297. +KS_DECLARE(ks_status_t) blade_module_data_get(blade_module_t *bm, void **data)
  298. +{
  299. +       ks_assert(bm);
  300. +       ks_assert(data);
  301. +
  302. +       *data = bm->module_data;
  303. +
  304. +       return KS_STATUS_SUCCESS;
  305. +}
  306. +
  307. +      
  308. +/* For Emacs:
  309. + * Local Variables:
  310. + * mode:c
  311. + * indent-tabs-mode:t
  312. + * tab-width:4
  313. + * c-basic-offset:4
  314. + * End:
  315. + * For VIM:
  316. + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  317. + */
  318. diff --git a/libs/libblade/src/blade_module_wss.c b/libs/libblade/src/blade_module_wss.c
  319. new file mode 100644
  320. index 0000000..589a172
  321. --- /dev/null
  322. +++ b/libs/libblade/src/blade_module_wss.c
  323. @@ -0,0 +1,626 @@
  324. +/*
  325. + * Copyright (c) 2017, Shane Bryldt
  326. + * All rights reserved.
  327. + *
  328. + * Redistribution and use in source and binary forms, with or without
  329. + * modification, are permitted provided that the following conditions
  330. + * are met:
  331. + *
  332. + * * Redistributions of source code must retain the above copyright
  333. + * notice, this list of conditions and the following disclaimer.
  334. + *
  335. + * * Redistributions in binary form must reproduce the above copyright
  336. + * notice, this list of conditions and the following disclaimer in the
  337. + * documentation and/or other materials provided with the distribution.
  338. + *
  339. + * * Neither the name of the original author; nor the names of any contributors
  340. + * may be used to endorse or promote products derived from this software
  341. + * without specific prior written permission.
  342. + *
  343. + *
  344. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  345. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  346. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  347. + * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  348. + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  349. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  350. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  351. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  352. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  353. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  354. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  355. + */
  356. +
  357. +#include "blade.h"
  358. +
  359. +#define BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX 16
  360. +
  361. +typedef struct blade_transport_wss_s blade_transport_wss_t;
  362. +
  363. +struct blade_module_wss_s {
  364. +       blade_handle_t *handle;
  365. +       ks_pool_t *pool;
  366. +       ks_thread_pool_t *tpool;
  367. +       blade_module_callbacks_t *module_callbacks;
  368. +       blade_transport_callbacks_t *transport_callbacks;
  369. +
  370. +       ks_sockaddr_t config_wss_endpoints_ipv4[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
  371. +       ks_sockaddr_t config_wss_endpoints_ipv6[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
  372. +       int32_t config_wss_endpoints_ipv4_length;
  373. +       int32_t config_wss_endpoints_ipv6_length;
  374. +       int32_t config_wss_endpoints_backlog;
  375. +
  376. +       ks_bool_t shutdown;
  377. +
  378. +       ks_thread_t *listeners_thread;
  379. +       struct pollfd *listeners_poll;
  380. +       int32_t listeners_count;
  381. +
  382. +       list_t connected;
  383. +       ks_q_t *disconnecting;
  384. +};
  385. +
  386. +struct blade_transport_wss_s {
  387. +       blade_module_wss_t *module;
  388. +       ks_pool_t *pool;
  389. +
  390. +       ks_socket_t sock;
  391. +       kws_t *kws;
  392. +};
  393. +
  394. +
  395. +
  396. +//ks_status_t blade_module_wss_create(blade_module_wss_t **bm_wssP, blade_handle_t *bh);
  397. +//ks_status_t blade_module_wss_destroy(blade_module_wss_t **bm_wssP);
  398. +
  399. +ks_status_t blade_module_wss_onload(blade_module_t **bmP, blade_handle_t *bh);
  400. +ks_status_t blade_module_wss_onunload(blade_module_t *bm);
  401. +ks_status_t blade_module_wss_onstartup(blade_module_t *bm, config_setting_t *config);
  402. +ks_status_t blade_module_wss_onshutdown(blade_module_t *bm);
  403. +
  404. +ks_status_t blade_module_wss_listen(blade_module_wss_t *bm, ks_sockaddr_t *addr);
  405. +void *blade_module_wss_listeners_thread(ks_thread_t *thread, void *data);
  406. +
  407. +
  408. +ks_status_t blade_transport_wss_create(blade_transport_wss_t **bt_wssP, blade_module_wss_t *bm_wss, ks_socket_t sock);
  409. +ks_status_t blade_transport_wss_destroy(blade_transport_wss_t **bt_wssP);
  410. +
  411. +ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target);
  412. +ks_status_t blade_transport_wss_onpulse(blade_connection_t *bc);
  413. +
  414. +
  415. +
  416. +static blade_module_wss_t g_module_wss; // @todo temporary, should be instanced in case multiple handles are created
  417. +
  418. +static blade_module_callbacks_t g_module_wss_callbacks =
  419. +{
  420. +       blade_module_wss_onload,
  421. +       blade_module_wss_onunload,
  422. +       blade_module_wss_onstartup,
  423. +       blade_module_wss_onshutdown,
  424. +};
  425. +
  426. +static blade_transport_callbacks_t g_transport_wss_callbacks =
  427. +{
  428. +       blade_transport_wss_onconnect,
  429. +       blade_transport_wss_onpulse,
  430. +       // @todo callback for a transport to rank routability of an identity, like blade_transport_wss_onroute(identity)
  431. +};
  432. +
  433. +
  434. +
  435. +//ks_status_t blade_module_wss_create(blade_module_wss_t **bm_wssP, blade_handle_t *bh)
  436. +
  437. +//ks_status_t blade_module_wss_destroy(blade_module_wss_t **bm_wssP)
  438. +
  439. +ks_status_t blade_module_wss_onload(blade_module_t **bmP, blade_handle_t *bh)
  440. +{
  441. +       ks_assert(bmP);
  442. +       ks_assert(bh);
  443. +
  444. +       memset(&g_module_wss, 0, sizeof(blade_module_wss_t));
  445. +
  446. +       g_module_wss.handle = bh;
  447. +       g_module_wss.pool = blade_handle_pool_get(bh);
  448. +       g_module_wss.tpool = blade_handle_tpool_get(bh);
  449. +       g_module_wss.module_callbacks = &g_module_wss_callbacks;
  450. +       g_module_wss.transport_callbacks = &g_transport_wss_callbacks;
  451. +       list_init(&g_module_wss.connected);
  452. +       ks_q_create(&g_module_wss.disconnecting, g_module_wss.pool, 0);
  453. +       ks_assert(g_module_wss.disconnecting);
  454. +
  455. +       blade_module_create(bmP, bh, &g_module_wss, &g_module_wss_callbacks);
  456. +
  457. +       return KS_STATUS_SUCCESS;
  458. +}
  459. +
  460. +ks_status_t blade_module_wss_onunload(blade_module_t *bm)
  461. +{
  462. +       ks_assert(bm);
  463. +
  464. +       blade_module_destroy(&bm);
  465. +      
  466. +       blade_module_wss_shutdown(bm);
  467. +
  468. +       //blade_module_wss_destroy(&bm);
  469. +
  470. +       list_destroy(&g_module.connected);
  471. +       ks_q_destroy(&g_module_wss.disconnecting);
  472. +
  473. +       return KS_STATUS_SUCCESS;
  474. +}
  475. +
  476. +ks_status_t blade_module_wss_config(blade_module_wss_t *bm_wss, config_setting_t *config)
  477. +{
  478. +       config_setting_t *wss = NULL;
  479. +       config_setting_t *wss_endpoints = NULL;
  480. +       config_setting_t *wss_endpoints_ipv4 = NULL;
  481. +       config_setting_t *wss_endpoints_ipv6 = NULL;
  482. +       config_setting_t *wss_ssl = NULL;
  483. +    config_setting_t *element;
  484. +       config_setting_t *tmp1;
  485. +       config_setting_t *tmp2;
  486. +       ks_sockaddr_t config_wss_endpoints_ipv4[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
  487. +       ks_sockaddr_t config_wss_endpoints_ipv6[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
  488. +       int32_t config_wss_endpoints_ipv4_length = 0;
  489. +       int32_t config_wss_endpoints_ipv6_length = 0;
  490. +       int32_t config_wss_endpoints_backlog = 8;
  491. +
  492. +       ks_assert(bm_wss);
  493. +       ks_assert(config);
  494. +
  495. +       if (!config_setting_is_group(config)) {
  496. +               ks_log(KS_LOG_DEBUG, "!config_setting_is_group(config)\n");
  497. +               return KS_STATUS_FAIL;
  498. +       }
  499. +
  500. +       wss = config_setting_get_member(config, "wss");
  501. +       if (!wss) {
  502. +               ks_log(KS_LOG_DEBUG, "!wss\n");
  503. +               return KS_STATUS_FAIL;
  504. +       }
  505. +       wss_endpoints = config_setting_get_member(wss, "endpoints");
  506. +       if (!wss_endpoints) {
  507. +               ks_log(KS_LOG_DEBUG, "!wss_endpoints\n");
  508. +               return KS_STATUS_FAIL;
  509. +       }
  510. +       wss_endpoints_ipv4 = config_lookup_from(wss_endpoints, "ipv4");
  511. +       wss_endpoints_ipv6 = config_lookup_from(wss_endpoints, "ipv6");
  512. +       if (wss_endpoints_ipv4) {
  513. +               if (config_setting_type(wss_endpoints_ipv4) != CONFIG_TYPE_LIST) return KS_STATUS_FAIL;
  514. +               if ((config_wss_endpoints_ipv4_length = config_setting_length(wss_endpoints_ipv4)) > BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX)
  515. +                       return KS_STATUS_FAIL;
  516. +              
  517. +               for (int32_t index = 0; index < config_wss_endpoints_ipv4_length; ++index) {
  518. +                       element = config_setting_get_elem(wss_endpoints_ipv4, index);
  519. +            tmp1 = config_lookup_from(element, "address");
  520. +            tmp2 = config_lookup_from(element, "port");
  521. +                       if (!tmp1 || !tmp2) return KS_STATUS_FAIL;
  522. +                       if (config_setting_type(tmp1) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL;
  523. +                       if (config_setting_type(tmp2) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
  524. +                      
  525. +                       if (ks_addr_set(&config_wss_endpoints_ipv4[index],
  526. +                                                       config_setting_get_string(tmp1),
  527. +                                                       config_setting_get_int(tmp2),
  528. +                                                       AF_INET) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
  529. +                       ks_log(KS_LOG_DEBUG,
  530. +                                  "Binding to IPV4 %s on port %d\n",
  531. +                                  ks_addr_get_host(&config_wss_endpoints_ipv4[index]),
  532. +                                  ks_addr_get_port(&config_wss_endpoints_ipv4[index]));
  533. +               }
  534. +       }
  535. +       if (wss_endpoints_ipv6) {
  536. +               if (config_setting_type(wss_endpoints_ipv6) != CONFIG_TYPE_LIST) return KS_STATUS_FAIL;
  537. +               if ((config_wss_endpoints_ipv6_length = config_setting_length(wss_endpoints_ipv6)) > BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX)
  538. +                       return KS_STATUS_FAIL;
  539. +              
  540. +               for (int32_t index = 0; index < config_wss_endpoints_ipv6_length; ++index) {
  541. +                       element = config_setting_get_elem(wss_endpoints_ipv6, index);
  542. +            tmp1 = config_lookup_from(element, "address");
  543. +            tmp2 = config_lookup_from(element, "port");
  544. +                       if (!tmp1 || !tmp2) return KS_STATUS_FAIL;
  545. +                       if (config_setting_type(tmp1) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL;
  546. +                       if (config_setting_type(tmp2) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
  547. +                      
  548. +                      
  549. +                       if (ks_addr_set(&config_wss_endpoints_ipv6[index],
  550. +                                                       config_setting_get_string(tmp1),
  551. +                                                       config_setting_get_int(tmp2),
  552. +                                                       AF_INET6) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
  553. +                       ks_log(KS_LOG_DEBUG,
  554. +                                  "Binding to IPV6 %s on port %d\n",
  555. +                                  ks_addr_get_host(&config_wss_endpoints_ipv6[index]),
  556. +                                  ks_addr_get_port(&config_wss_endpoints_ipv6[index]));
  557. +               }
  558. +       }
  559. +       if (config_wss_endpoints_ipv4_length + config_wss_endpoints_ipv6_length <= 0) return KS_STATUS_FAIL;
  560. +       tmp1 = config_lookup_from(wss_endpoints, "backlog");
  561. +       if (tmp1) {
  562. +               if (config_setting_type(tmp1) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
  563. +               config_wss_endpoints_backlog = config_setting_get_int(tmp1);
  564. +       }
  565. +       wss_ssl = config_setting_get_member(wss, "ssl");
  566. +       if (wss_ssl) {
  567. +               // @todo: SSL stuffs from wss_ssl into config_wss_ssl envelope
  568. +       }
  569. +
  570. +
  571. +       // Configuration is valid, now assign it to the variables that are used
  572. +       // If the configuration was invalid, then this does not get changed
  573. +       for (int32_t index = 0; index < config_wss_endpoints_ipv4_length; ++index)
  574. +               bm_wss->config_wss_endpoints_ipv4[index] = config_wss_endpoints_ipv4[index];
  575. +       for (int32_t index = 0; index < config_wss_endpoints_ipv6_length; ++index)
  576. +               bm_wss->config_wss_endpoints_ipv6[index] = config_wss_endpoints_ipv6[index];
  577. +       bm_wss->config_wss_endpoints_ipv4_length = config_wss_endpoints_ipv4_length;
  578. +       bm_wss->config_wss_endpoints_ipv6_length = config_wss_endpoints_ipv6_length;
  579. +       bm_wss->config_wss_endpoints_backlog = config_wss_endpoints_backlog;
  580. +       //bm_wss->config_wss_ssl = config_wss_ssl;
  581. +
  582. +       return KS_STATUS_SUCCESS;
  583. +}
  584. +
  585. +ks_status_t blade_module_wss_onstartup(blade_module_t *bm, config_setting_t *config)
  586. +{
  587. +       blade_module_wss_t *bm_wss = NULL;
  588. +      
  589. +       ks_assert(bm);
  590. +       ks_assert(config);
  591. +
  592. +       bm_wss = (blade_module_wss_t *)blade_module_data_get(bm);
  593. +
  594. +    if (blade_module_wss_config(bm_wss, config) != KS_STATUS_SUCCESS) {
  595. +               ks_log(KS_LOG_DEBUG, "blade_module_wss_config failed\n");
  596. +               return KS_STATUS_FAIL;
  597. +       }
  598. +
  599. +       for (int32_t index = 0; index < bm_wss->config_wss_endpoints_ipv4_length; ++index) {
  600. +               if (blade_module_wss_listen(bm_wss, &bm_wss->config_wss_endpoints_ipv4[index]) != KS_STATUS_SUCCESS) {
  601. +                       ks_log(KS_LOG_DEBUG, "blade_module_wss_listen (v4) failed\n");
  602. +                       return KS_STATUS_FAIL;
  603. +               }
  604. +       }
  605. +       for (int32_t index = 0; index < bm_wss->config_wss_endpoints_ipv6_length; ++index) {
  606. +               if (blade_module_wss_listen(bm_wss, &bm_wss->config_wss_endpoints_ipv6[index]) != KS_STATUS_SUCCESS) {
  607. +                       ks_log(KS_LOG_DEBUG, "blade_module_wss_listen (v6) failed\n");
  608. +                       return KS_STATUS_FAIL;
  609. +               }
  610. +       }
  611. +
  612. +       if (ks_thread_create_ex(&bm_wss->listeners_thread,
  613. +                                                       blade_module_wss_listeners_thread,
  614. +                                                       bm_wss,
  615. +                                                       KS_THREAD_FLAG_DEFAULT,
  616. +                                                       KS_THREAD_DEFAULT_STACK,
  617. +                                                       KS_PRI_NORMAL,
  618. +                                                       bm_wss->pool) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
  619. +      
  620. +       return KS_STATUS_SUCCESS;
  621. +}
  622. +
  623. +ks_status_t blade_module_wss_onshutdown(blade_module_t *bm)
  624. +{
  625. +       blade_module_wss_t *bm_wss = NULL;
  626. +       blade_transport_wss_t *bt_wss = NULL;
  627. +       blade_connection_t *conn = NULL;
  628. +      
  629. +       ks_assert(bm);
  630. +
  631. +       bm_wss = (blade_module_wss_t *)blade_module_data_get(bm);
  632. +
  633. +       if (bm_wss->listeners_thread) {
  634. +               bm_wss->shutdown = KS_TRUE;
  635. +               ks_thread_join(bm_wss->listeners_thread);
  636. +               ks_pool_free(bm_wss->pool, &bm_wss->listeners_thread);
  637. +               bm_wss->shutdown = KS_FALSE;
  638. +       }
  639. +
  640. +       for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
  641. +               ks_socket_t sock = bm_wss->listeners_poll[index].fd;
  642. +               ks_socket_shutdown(sock, SHUT_RDWR);
  643. +               ks_socket_close(&sock);
  644. +       }
  645. +       bm_wss->listeners_count = 0;
  646. +       if (bm_wss->listeners_poll) ks_pool_free(bm_wss->pool, &bm_wss->listeners_poll);
  647. +
  648. +       while (ks_q_trypop(bm_wss->disconnecting, &conn) == KS_STATUS_SUCCESS) ;
  649. +       list_iterator_start(&bm_wss->connected);
  650. +       while (list_iterator_hasnext(&bm_wss->connected)) {
  651. +               conn = (blade_connection_t *)list_iterator_next(&bm_wss->connected);
  652. +               trans = (blade_transport_wss_t *)blade_connection_transport_get(conn);
  653. +
  654. +               blade_connection_destroy(&conn);
  655. +               blade_transport_wss_destroy(&trans);
  656. +       }
  657. +       list_iterator_stop(&bm_wss->connected);
  658. +       list_clear(&bm_wss->connected);
  659. +
  660. +       return KS_STATUS_SUCCESS;
  661. +}
  662. +
  663. +ks_status_t blade_module_wss_listen(blade_module_wss_t *bm_wss, ks_sockaddr_t *addr)
  664. +{
  665. +       ks_socket_t listener = KS_SOCK_INVALID;
  666. +       int32_t listener_index = -1;
  667. +       ks_status_t ret = KS_STATUS_SUCCESS;
  668. +      
  669. +       ks_assert(bm_wss);
  670. +       ks_assert(addr);
  671. +
  672. +       if ((listener = socket(addr->family, SOCK_STREAM, IPPROTO_TCP)) == KS_SOCK_INVALID) {
  673. +               ks_log(KS_LOG_DEBUG, "listener == KS_SOCK_INVALID\n");
  674. +               ret = KS_STATUS_FAIL;
  675. +               goto done;
  676. +       }
  677. +
  678. +       ks_socket_option(listener, SO_REUSEADDR, KS_TRUE);
  679. +       ks_socket_option(listener, TCP_NODELAY, KS_TRUE);
  680. +       if (addr->family == AF_INET6) ks_socket_option(listener, IPV6_V6ONLY, KS_TRUE);
  681. +
  682. +       if (ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS) {
  683. +               ks_log(KS_LOG_DEBUG, "ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS\n");
  684. +               ret = KS_STATUS_FAIL;
  685. +               goto done;
  686. +       }
  687. +
  688. +       if (listen(listener, bm_wss->config_wss_endpoints_backlog) != 0) {
  689. +               ks_log(KS_LOG_DEBUG, "listen(listener, backlog) != 0\n");
  690. +               ret = KS_STATUS_FAIL;
  691. +               goto done;
  692. +       }
  693. +
  694. +       listener_index = bm_wss->listeners_count++;
  695. +       bm_wss->listeners_poll = (struct pollfd *)ks_pool_resize(bm_wss->pool,
  696. +                                                                                                                        bm_wss->listeners_poll,
  697. +                                                                                                                        sizeof(struct pollfd) * bm_wss->listeners_count);
  698. +       ks_assert(bm_wss->listeners_poll);
  699. +       bm_wss->listeners_poll[listener_index].fd = listener;
  700. +       bm_wss->listeners_poll[listener_index].events = POLLIN | POLLERR;
  701. +
  702. + done:
  703. +       if (ret != KS_STATUS_SUCCESS) {
  704. +               if (listener != KS_SOCK_INVALID) {
  705. +                       ks_socket_shutdown(listener, SHUT_RDWR);
  706. +                       ks_socket_close(&listener);
  707. +               }
  708. +       }
  709. +       return ret;
  710. +}
  711. +
  712. +void *blade_module_wss_listeners_thread(ks_thread_t *thread, void *data)
  713. +{
  714. +       blade_module_wss_t *bm_wss = NULL;
  715. +       blade_transport_wss_t *bt_wss = NULL;
  716. +       blade_connection_t *bc = NULL;
  717. +
  718. +       ks_assert(thread);
  719. +       ks_assert(data);
  720. +
  721. +       bm_wss = (blade_module_wss_t *)data;
  722. +
  723. +       ks_log(KS_LOG_DEBUG, "Module running\n");
  724. +      
  725. +       while (!bm_wss->shutdown) {
  726. +               // @todo take exact timeout from a setting in config_wss_endpoints
  727. +               if (ks_poll(bm_wss->listeners_poll, bm_wss->listeners_count, 100) > 0) {
  728. +                       for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
  729. +                               ks_socket_t sock = KS_SOCK_INVALID;
  730. +
  731. +                               if (!(bm_wss->listeners_poll[index].revents & POLLIN)) continue;
  732. +                               if (bm_wss->listeners_poll[index].revents & POLLERR) {
  733. +                                       // @todo: error handling, just skip the listener for now, it might recover, could skip X times before closing?
  734. +                                       continue;
  735. +                               }
  736. +
  737. +                               if ((sock = accept(bm_wss->listeners_poll[index].fd, NULL, NULL)) == KS_SOCK_INVALID) {
  738. +                                       // @todo: error handling, just skip the socket for now as most causes are because remote side became unreachable
  739. +                                       continue;
  740. +                               }
  741. +
  742. +                               blade_transport_wss_create(&bt_wss, bm_wss, sock);
  743. +                               ks_assert(bt_wss);
  744. +                              
  745. +                blade_connection_create(&bc, bm_wss->handle, bt_wss, bm_wss->transport_callbacks);
  746. +                               ks_assert(bc);
  747. +
  748. +                               blade_connection_startup(bc);
  749. +
  750. +                               list_append(&bm_wss->connected, bc);
  751. +
  752. +                               blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NEW);
  753. +                       }
  754. +               }
  755. +
  756. +               while (ks_q_trypop(bm_wss->disconnecting, &bc) == KS_STATUS_SUCCESS) {
  757. +                       bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
  758. +
  759. +                       list_delete(&bm_wss->connected, bc);
  760. +
  761. +                       blade_connection_destroy(&bc);
  762. +                       blade_transport_wss_destroy(&bt_wss);
  763. +               }
  764. +       }
  765. +
  766. +    return NULL;
  767. +}
  768. +
  769. +
  770. +
  771. +ks_status_t blade_transport_wss_create(blade_transport_wss_t **bt_wssP, blade_module_wss_t *bm_wss, ks_socket_t sock)
  772. +{
  773. +       blade_transport_wss_t *bt_wss = NULL;
  774. +
  775. +       ks_assert(bt_wssP);
  776. +       ks_assert(bm_wss);
  777. +       ks_assert(sock != KS_SOCK_INVALID);
  778. +
  779. +    bt_wss = ks_pool_alloc(bm_wss->pool, sizeof(blade_transport_wss_t));
  780. +       bt_wss->module = bm_wss;
  781. +       bt_wss->pool = bm_wss->pool;
  782. +       bt_wss->sock = sock;
  783. +
  784. +       *bt_wssP = bt_wss;
  785. +      
  786. +       return KS_STATUS_SUCCESS;
  787. +}
  788. +
  789. +ks_status_t blade_transport_wss_destroy(blade_transport_wss_t **bt_wssP)
  790. +{
  791. +       blade_transport_wss_t *bt_wss = NULL;
  792. +      
  793. +       ks_assert(bt_wssP);
  794. +       ks_assert(*bt_wssP);
  795. +
  796. +       bt_wss = *bt_wssP;
  797. +
  798. +       if (bt_wss->kws) kws_destroy(&bt_wss->kws);
  799. +       else ks_socket_close(bt_wss->sock);
  800. +      
  801. +       ks_pool_free(bt_wss->pool, bt_wssP);
  802. +      
  803. +       return KS_STATUS_SUCCESS;
  804. +}
  805. +
  806. +ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target)
  807. +{
  808. +       ks_assert(bcP);
  809. +       ks_assert(bh);
  810. +       ks_assert(target);
  811. +
  812. +       *bcP = NULL;
  813. +
  814. +       // @todo connect-out equivilent of accept
  815. +
  816. +       return KS_STATUS_SUCCESS;
  817. +}
  818. +
  819. +ks_status_t blade_transport_wss_read(blade_transport_wss_t *bt_wss, cJSON **json)
  820. +{
  821. +       // @todo get exact timeout from service config?
  822. +       int32_t poll_flags = ks_wait_sock(bt_wss->sock, 100, KS_POLL_READ | KS_POLL_ERROR);
  823. +
  824. +       *json = NULL;
  825. +
  826. +       if (poll_flags & KS_POLL_ERROR) {
  827. +               // @todo error logging
  828. +               return KS_STATUS_FAIL;
  829. +       }
  830. +       if (poll_flags & KS_POLL_READ) {
  831. +               kws_opcode_t opcode;
  832. +               uint8_t *frame_data = NULL;
  833. +               ks_size_t frame_data_len = kws_read_frame(bt_wss->kws, &opcode, &frame_data);
  834. +
  835. +               if (frame_data_len <= 0) {
  836. +                       // @todo error logging, strerror(ks_errno())
  837. +                       // 0 means socket closed with WS_NONE, which closes websocket with no additional reason
  838. +                       // -1 means socket closed with a general failure
  839. +                       // -2 means nonblocking wait
  840. +                       // other values are based on WS_XXX reasons
  841. +                       // negative values are based on reasons, except for -1 is but -2 is nonblocking wait, and
  842. +                       return KS_STATUS_FAIL;
  843. +               }
  844. +
  845. +               //if (blade_handle_message_claim(blade_service_handle(peer->service), &message, frame_data, frame_data_len) != KS_STATUS_SUCCESS || !message) {
  846. +               // @todo error logging
  847. +               //      return KS_STATUS_FAIL;
  848. +               //}
  849. +                              
  850. +               // @todo convert frame_data to cJSON safely, make sure data is null-terminated at frame_data_len
  851. +               if (!(*json = cJSON_Parse(frame_data))) {
  852. +                       return KS_STATUS_FAIL;
  853. +               }
  854. +       }
  855. +       return KS_STATUS_SUCCESS;
  856. +}
  857. +
  858. +ks_status_t blade_transport_wss_write(blade_transport_wss_t *bt_wss, cJSON *json)
  859. +{
  860. +       //blade_message_get(message, &target, &json);
  861. +       char *json_str = cJSON_PrintUnformatted(json);
  862. +       ks_size_t json_str_len = 0;
  863. +       if (!json_str) {
  864. +               // @todo error logging
  865. +               return KS_STATUS_FAIL;
  866. +       }
  867. +       json_str_len = strlen(json_str) + 1;
  868. +       kws_write_frame(bt_wss->kws, WSOC_TEXT, json_str, json_str_len);
  869. +                              
  870. +       cJSON_free(jsonstr);
  871. +      
  872. +       return KS_STATUS_SUCCESS;
  873. +}
  874. +
  875. +ks_status_t blade_transport_wss_onpulse(blade_connection_t *bc)
  876. +{
  877. +       blade_connection_state_t state;
  878. +       blade_transport_wss_t *bt_wss = NULL;
  879. +       cJSON *json = NULL;
  880. +
  881. +       ks_assert(bc);
  882. +
  883. +       state = blade_connection_state_get(bc);
  884. +       bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
  885. +
  886. +       switch (state) {
  887. +       case BLADE_CONNECTION_STATE_NEW:
  888. +               {
  889. +                       // @todo: SSL init stuffs based on data from peer->service->config_websockets_ssl to pass into kws_init
  890. +                       if (kws_init(&bt_wss->kws, bt_wss->sock, NULL, NULL, KWS_BLOCK, bt_wss->pool) != KS_STATUS_SUCCESS) {
  891. +                               // @todo error logging
  892. +                               return KS_STATUS_FAIL;
  893. +                       }
  894. +                       blade_connection_state_set(bc, BLADE_CONNECTION_STATE_CONNECTIN);
  895. +                       break;
  896. +               }
  897. +       case BLADE_CONNECTION_STATE_DISCONNECT:
  898. +               {
  899. +                       ks_q_push(bt_wss->module->disconnecting, conn);
  900. +                       blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NONE);
  901. +                       break;
  902. +               }
  903. +       case BLADE_CONNECTION_STATE_CONNECTIN:
  904. +               {
  905. +                       if (blade_transport_wss_read(bt_wss, &json) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
  906. +
  907. +                       if (json) {
  908. +                               // @todo processing connectin messages for identity registration
  909. +                               cJSON_Delete(json);
  910. +                               //blade_connection_receiving_push(conn, json);
  911. +                       }
  912. +
  913. +                       // @todo wrap identity + json into an envelope for queueing through the connection, but target should be included in the json already
  914. +                       while (blade_connection_sending_pop(conn, (void **)&json) == KS_STATUS_SUCCESS && json) {
  915. +                               ks_status_t ret = blade_transport_wss_write(bt_wss, json);
  916. +                               cJSON_Delete(json);
  917. +                               if (ret != KS_STATUS_SUCCESS) return ret;
  918. +                       }
  919. +                       break;
  920. +               }
  921. +       default: break;
  922. +       }
  923. +      
  924. +       return KS_STATUS_SUCCESS;
  925. +}
  926. +
  927. +ks_status_t blade_transport_wss_onsend(blade_connection_t *bc, blade_identity_t *target, cJSON *message)
  928. +{
  929. +       //blade_transport_wss_t *trans = NULL;
  930. +
  931. +       ks_assert(bc);
  932. +       ks_assert(target);
  933. +       ks_assert(message);
  934. +
  935. +       //trans = (blade_transport_wss_t *)blade_connection_transport_get(bc);
  936. +
  937. +       return KS_STATUS_SUCCESS;
  938. +}
  939. +
  940. +/* For Emacs:
  941. + * Local Variables:
  942. + * mode:c
  943. + * indent-tabs-mode:t
  944. + * tab-width:4
  945. + * c-basic-offset:4
  946. + * End:
  947. + * For VIM:
  948. + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  949. + */
  950. diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c
  951. index 8504af0..688136c 100644
  952. --- a/libs/libblade/src/blade_stack.c
  953. +++ b/libs/libblade/src/blade_stack.c
  954. @@ -184,6 +184,18 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh)
  955.         return KS_STATUS_SUCCESS;
  956.  }
  957.  
  958. +KS_DECLARE(ks_pool_t *) blade_handle_pool_get(blade_handle_t *bh)
  959. +{
  960. +       ks_assert(bh);
  961. +       return bh->pool;
  962. +}
  963. +
  964. +KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh)
  965. +{
  966. +       ks_assert(bh);
  967. +       return bh->tpool;
  968. +}
  969. +
  970.  KS_DECLARE(ks_status_t) blade_handle_message_claim(blade_handle_t *bh, blade_message_t **message, void *data, ks_size_t data_length)
  971.  {
  972.         blade_message_t *msg = NULL;
  973. diff --git a/libs/libblade/src/include/blade.h b/libs/libblade/src/include/blade.h
  974. index f8a3a44..e749212 100644
  975. --- a/libs/libblade/src/include/blade.h
  976. +++ b/libs/libblade/src/include/blade.h
  977. @@ -46,6 +46,8 @@
  978.  #include "blade_datastore.h"
  979.  #include "bpcp.h"
  980.  
  981. +#include "blade_module.h"
  982. +
  983.  KS_BEGIN_EXTERN_C
  984.  
  985.  KS_DECLARE(ks_status_t) blade_init(void);
  986. diff --git a/libs/libblade/src/include/blade_module.h b/libs/libblade/src/include/blade_module.h
  987. new file mode 100644
  988. index 0000000..d9fcca8
  989. --- /dev/null
  990. +++ b/libs/libblade/src/include/blade_module.h
  991. @@ -0,0 +1,55 @@
  992. +/*
  993. + * Copyright (c) 2017, Shane Bryldt
  994. + * All rights reserved.
  995. + *
  996. + * Redistribution and use in source and binary forms, with or without
  997. + * modification, are permitted provided that the following conditions
  998. + * are met:
  999. + *
  1000. + * * Redistributions of source code must retain the above copyright
  1001. + * notice, this list of conditions and the following disclaimer.
  1002. + *
  1003. + * * Redistributions in binary form must reproduce the above copyright
  1004. + * notice, this list of conditions and the following disclaimer in the
  1005. + * documentation and/or other materials provided with the distribution.
  1006. + *
  1007. + * * Neither the name of the original author; nor the names of any contributors
  1008. + * may be used to endorse or promote products derived from this software
  1009. + * without specific prior written permission.
  1010. + *
  1011. + *
  1012. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  1013. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  1014. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  1015. + * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  1016. + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  1017. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  1018. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  1019. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  1020. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  1021. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  1022. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1023. + */
  1024. +
  1025. +#ifndef _BLADE_MODULE_H_
  1026. +#define _BLADE_MODULE_H_
  1027. +#include <blade.h>
  1028. +
  1029. +KS_BEGIN_EXTERN_C
  1030. +KS_DECLARE(ks_status_t) blade_module_create(blade_module_t **bmP, blade_handle_t *bh, void *module_data, blade_module_callbacks_t *module_callbacks);
  1031. +KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP);
  1032. +KS_DECLARE(ks_status_t) blade_module_data_get(blade_module_t *bm, void **data);
  1033. +KS_END_EXTERN_C
  1034. +
  1035. +#endif
  1036. +
  1037. +/* For Emacs:
  1038. + * Local Variables:
  1039. + * mode:c
  1040. + * indent-tabs-mode:t
  1041. + * tab-width:4
  1042. + * c-basic-offset:4
  1043. + * End:
  1044. + * For VIM:
  1045. + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  1046. + */
  1047. diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h
  1048. index ff44f23..57ac554 100644
  1049. --- a/libs/libblade/src/include/blade_stack.h
  1050. +++ b/libs/libblade/src/include/blade_stack.h
  1051. @@ -45,6 +45,8 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP);
  1052.  KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool, ks_thread_pool_t *tpool);
  1053.  KS_DECLARE(ks_status_t) blade_handle_startup(blade_handle_t *bh, config_setting_t *config, blade_service_peer_state_callback_t service_peer_state_callback);
  1054.  KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh);
  1055. +KS_DECLARE(ks_pool_t *) blade_handle_pool_get(blade_handle_t *bh);
  1056. +KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh);
  1057.  
  1058.  KS_DECLARE(ks_status_t) blade_handle_message_claim(blade_handle_t *bh, blade_message_t **message, void *data, ks_size_t data_length);
  1059.  KS_DECLARE(ks_status_t) blade_handle_message_discard(blade_handle_t *bh, blade_message_t **message);
  1060. diff --git a/libs/libblade/src/include/blade_types.h b/libs/libblade/src/include/blade_types.h
  1061. index b534fde..966de73 100644
  1062. --- a/libs/libblade/src/include/blade_types.h
  1063. +++ b/libs/libblade/src/include/blade_types.h
  1064. @@ -59,6 +59,33 @@ typedef struct blade_datastore_s blade_datastore_t;
  1065.  typedef void (*blade_service_peer_state_callback_t)(blade_service_t *bs, blade_peer_t *bp, blade_peerstate_t state);
  1066.  typedef ks_bool_t (*blade_datastore_fetch_callback_t)(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata);
  1067.  
  1068. +
  1069. +
  1070. +typedef struct blade_module_s blade_module_t;
  1071. +typedef struct blade_module_callbacks_s blade_module_callbacks_t;
  1072. +typedef struct blade_transport_callbacks_s blade_transport_callbacks_t;
  1073. +
  1074. +typedef ks_status_t (*blade_module_load_callback_t)(blade_module_t **bmP, blade_handle_t *bh);
  1075. +typedef ks_status_t (*blade_module_unload_callback_t)(blade_module_t *bm);
  1076. +typedef ks_status_t (*blade_module_startup_callback_t)(blade_module_t *bm, config_setting_t *config);
  1077. +typedef ks_status_t (*blade_module_shutdown_callback_t)(blade_module_t *bm);
  1078. +
  1079. +struct blade_module_callbacks_s {
  1080. +       blade_module_load_callback_t onload;
  1081. +       blade_module_unload_callback_t onunload;
  1082. +       blade_module_startup_callback_t onstartup;
  1083. +       blade_module_shutdown_callback_t onshutdown;
  1084. +};
  1085. +
  1086. +typedef ks_status_t (*blade_transport_connect_callback_t)(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target);
  1087. +typedef ks_status_t (*blade_transport_pulse_callback_t)(blade_connection_t *bc);
  1088. +
  1089. +struct blade_transport_callbacks_s {
  1090. +       blade_transport_connect_callback_t onconnect;
  1091. +       blade_transport_pulse_callback_t onpulse;
  1092. +};
  1093. +
  1094. +
  1095.  KS_END_EXTERN_C
  1096.  
  1097.  #endif
  1098.