main.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * Copyright (c) 2018 SignalWire, Inc
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. #include "signalwire-client-c/client.h"
  23. #if 0
  24. #define REQUIRE(x) ks_assertd(x)
  25. static swclt_sess_t g_session;
  26. static const char *g_bench_protocol = "bench";
  27. static const char *g_bench_channel = "swbench";
  28. static const char *g_bench_event = "report";
  29. static ks_status_t g_bench_thread_status;
  30. static ks_throughput_t g_throughput_send;
  31. static ks_throughput_t g_throughput_recv;
  32. #define TEST_DURATION_SEC 50000000
  33. /* Define our properties for this benchmark */
  34. static SSL_CTX * __create_ssl_ctx()
  35. {
  36. static const char *key = "ca/intermediate/private/client@freeswitch-upstream.key.pem";
  37. static const char *cert = "ca/intermediate/certs/client@freeswitch-upstream.cert.pem";
  38. static const char *chain = "ca/intermediate/certs/ca-chain.cert.pem";
  39. SSL_CTX *ssl;
  40. REQUIRE(!swclt_ssl_create_context(key, cert, chain, &ssl));
  41. return ssl;
  42. }
  43. void render_stats(const char *header)
  44. {
  45. printf("%s\n", header);
  46. printf("Send: %s\n", ks_handle_describe(g_throughput_send));
  47. printf("Recv: %s\n", ks_handle_describe(g_throughput_recv));
  48. }
  49. void on_bench_event(
  50. swclt_sess_t sess,
  51. blade_broadcast_rqu_t *rqu,
  52. void *cb_data)
  53. {
  54. ks_json_t *object = BLADE_BROADCAST_RQU_MARSHAL(NULL, *rqu);
  55. KS_JSON_PRINT("Got bench event:", object);
  56. ks_json_delete(&object);
  57. }
  58. SWCLT_JSON_MARSHAL_BEG(THROUGHPUT_STATS, ks_throughput_stats_t)
  59. SWCLT_JSON_MARSHAL_INT(size)
  60. SWCLT_JSON_MARSHAL_INT(count)
  61. SWCLT_JSON_MARSHAL_DOUBLE(rate_size)
  62. SWCLT_JSON_MARSHAL_DOUBLE(rate_count)
  63. SWCLT_JSON_MARSHAL_INT_EX(run_time_sec, run_time)
  64. SWCLT_JSON_MARSHAL_END()
  65. SWCLT_JSON_DESTROY_BEG(THROUGHPUT_STATS, ks_throughput_stats_t)
  66. SWCLT_JSON_DESTROY_INT(size)
  67. SWCLT_JSON_DESTROY_INT(count)
  68. SWCLT_JSON_DESTROY_DOUBLE(rate_size)
  69. SWCLT_JSON_DESTROY_DOUBLE(rate_count)
  70. SWCLT_JSON_DESTROY_INT_EX(run_time_sec, run_time)
  71. SWCLT_JSON_DESTROY_END()
  72. SWCLT_JSON_PARSE_BEG(THROUGHPUT_STATS, ks_throughput_stats_t)
  73. SWCLT_JSON_PARSE_INT(size)
  74. SWCLT_JSON_PARSE_INT(count)
  75. SWCLT_JSON_PARSE_DOUBLE(rate_size)
  76. SWCLT_JSON_PARSE_DOUBLE(rate_count)
  77. SWCLT_JSON_PARSE_INT_EX(run_time_sec, run_time)
  78. SWCLT_JSON_PARSE_END()
  79. /* Define our benchmark payloads */
  80. typedef struct benchmark_payload_s {
  81. ks_throughput_stats_t *conn_recv_stats;
  82. ks_throughput_stats_t *conn_send_stats;
  83. } benchmark_payload_t;
  84. SWCLT_JSON_MARSHAL_BEG(BENCHMARK_PAYLOAD, benchmark_payload_t)
  85. SWCLT_JSON_MARSHAL_CUSTOM(THROUGHPUT_STATS, conn_recv_stats)
  86. SWCLT_JSON_MARSHAL_CUSTOM(THROUGHPUT_STATS, conn_send_stats)
  87. SWCLT_JSON_MARSHAL_END()
  88. SWCLT_JSON_DESTROY_BEG(BENCHMARK_PAYLOAD, benchmark_payload_t)
  89. SWCLT_JSON_DESTROY_CUSTOM(THROUGHPUT_STATS, conn_recv_stats)
  90. SWCLT_JSON_DESTROY_CUSTOM(THROUGHPUT_STATS, conn_send_stats)
  91. SWCLT_JSON_DESTROY_END()
  92. SWCLT_JSON_PARSE_BEG(BENCHMARK_PAYLOAD, benchmark_payload_t)
  93. SWCLT_JSON_PARSE_CUSTOM(THROUGHPUT_STATS, conn_recv_stats)
  94. SWCLT_JSON_PARSE_CUSTOM(THROUGHPUT_STATS, conn_send_stats)
  95. SWCLT_JSON_PARSE_END()
  96. ks_json_t * __create_bench_payload()
  97. {
  98. ks_throughput_stats_t recv, send;
  99. benchmark_payload_t payload = {&recv, &send};
  100. REQUIRE(!ks_throughput_stats(g_throughput_recv, &recv));
  101. REQUIRE(!ks_throughput_stats(g_throughput_send, &send));
  102. return BENCHMARK_PAYLOAD_MARSHAL(NULL, payload);
  103. }
  104. void * bench_thread_run(ks_thread_t *thread, void *data)
  105. {
  106. ks_time_t start = ks_time_now_sec();
  107. ks_time_t last_update = start;
  108. printf("Bench thread is active\n");
  109. while (!ks_thread_stop_requested(thread)) {
  110. ks_json_t *bench_payload = __create_bench_payload();
  111. if (g_bench_thread_status = swclt_sess_broadcast(
  112. g_session,
  113. g_bench_protocol,
  114. g_bench_channel,
  115. g_bench_event,
  116. bench_payload
  117. )) {
  118. ks_json_delete(&bench_payload);
  119. printf("Bench errored on broadcast: %d\n", g_bench_thread_status);
  120. break;
  121. }
  122. ks_json_delete(&bench_payload);
  123. if (ks_time_now_sec() - last_update > 1) {
  124. render_stats("Stats");
  125. last_update = ks_time_now_sec();
  126. }
  127. if ((ks_time_now_sec() - start) >= TEST_DURATION_SEC)
  128. break;
  129. }
  130. printf("Bench thread exiting with final status: %d\n", g_bench_thread_status);
  131. return NULL;
  132. }
  133. ks_status_t do_bench()
  134. {
  135. ks_thread_t *bench_thread = NULL;
  136. ks_status_t status;
  137. /* Start a bench thread */
  138. if (status = ks_thread_create(&bench_thread, bench_thread_run, NULL, NULL))
  139. return status;
  140. /* And let it do its thing */
  141. ks_thread_join(bench_thread);
  142. ks_thread_destroy(&bench_thread);
  143. return g_bench_thread_status;
  144. }
  145. int main(int argc, char **argv)
  146. {
  147. static const char *key = "ca/intermediate/private/client@freeswitch-upstream.key.pem";
  148. static const char *cert = "ca/intermediate/certs/client@freeswitch-upstream.cert.pem";
  149. static const char *chain = "ca/intermediate/certs/ca-chain.cert.pem";
  150. swclt_sub_t sub;
  151. ks_status_t status;
  152. const char *identity;
  153. swclt_cfg_t swclt_cfg, bench_cfg;
  154. swclt_sess_info_t info;
  155. if (status = swclt_init(KS_LOG_LEVEL_DEBUG))
  156. return status;
  157. if (status = swclt_cfg_open_ex(&bench_cfg, "swclt_bench.cfg", "benchmark"))
  158. goto done;
  159. if (status = swclt_cfg_open_ex(&swclt_cfg, "swclt_bench.cfg", "signalwire_client"))
  160. goto done;
  161. if (status = swclt_cfg_get_strval(bench_cfg, "target_identity", &identity))
  162. goto done;
  163. printf("swclt_bench starting, connecting to %s\n", identity);
  164. if (status = swclt_sess_create(&g_session, identity, swclt_cfg))
  165. goto done;
  166. /* Watch the session for state changes, anytime it goes normal we'll
  167. * start pumping the benchmark payloads */
  168. if (status = swclt_handle_register_state_change_listener(
  169. #define swclt_handle_register_state_change_listener(ctx, cb, handle) __swclt_handle_register_state_change_listener((swclt_handle_base_t *)ctx, (swclt_hstate_change_cb_t)cb, handle)
  170. /* Initiate the connect phase */
  171. if (status = swclt_sess_connect(g_session))
  172. goto done;
  173. if (status = swclt_sess_info(g_session, &info)) {
  174. printf("Failed to get session info: %d\n", status);
  175. goto done;
  176. }
  177. printf("Successfully allocated session: %s\n", ks_handle_describe(g_session));
  178. /* Grab a copy of the rate reporters so we can report our rate */
  179. swclt_sess_get_rates(g_session, &g_throughput_recv, &g_throughput_send);
  180. printf("Publishing bench channel\n");
  181. /* Publish a bench channel */
  182. if (status = swclt_sess_provider_add(g_session, g_bench_protocol,
  183. (blade_channel_t){g_bench_channel, BLADE_ACL_PUBLIC},
  184. BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC, BLADE_ACL_PUBLIC)) {
  185. printf("Failed to publish bench protocol: %d\n", status);
  186. goto done;
  187. }
  188. printf("Successfully published bench channel, subscribing next...");
  189. /* And subscribe to it */
  190. if (status = swclt_sess_subscription_add(
  191. g_session,
  192. g_bench_protocol,
  193. g_bench_channel,
  194. &on_bench_event,
  195. NULL,
  196. &sub)) {
  197. printf("Failed to subscribe to bench channel: %d", status);
  198. goto done;
  199. }
  200. printf("Successfully subscribed to bench channel, starting bench thread");
  201. ;
  202. /* Kick off the bench loop */
  203. if (status = do_bench()) {
  204. printf("Bench failed: %d", status);
  205. goto done;
  206. }
  207. ks_throughput_stop(g_throughput_send);
  208. ks_throughput_stop(g_throughput_recv);
  209. render_stats("Final stats");
  210. done:
  211. ks_handle_destroy(&g_session);
  212. swclt_shutdown();
  213. return status;
  214. }
  215. #endif
  216. int main(int argc, char **argv)
  217. {
  218. /** @@ TODo **/
  219. return -1;
  220. }