main.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * lws-api-test-lws_smd
  3. *
  4. * Written in 2020 by Andy Green <[email protected]>
  5. *
  6. * This file is made available under the Creative Commons CC0 1.0
  7. * Universal Public Domain Dedication.
  8. *
  9. * This api test confirms lws_smd System Message Distribution
  10. */
  11. #include <libwebsockets.h>
  12. #define HAVE_STRUCT_TIMESPEC
  13. #include <pthread.h>
  14. #include <signal.h>
  15. static int interrupted, ok, fail, _exp = 111;
  16. static lws_sorted_usec_list_t sul;
  17. struct lws_context *context;
  18. static pthread_t thread_spam;
  19. static void
  20. timeout_cb(lws_sorted_usec_list_t *sul)
  21. {
  22. /* We should have completed the test before this fires */
  23. interrupted = 1;
  24. lws_cancel_service(context);
  25. }
  26. static int
  27. smd_cb1int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
  28. void *buf, size_t len)
  29. {
  30. #if 0
  31. lwsl_notice("%s: ts %llu, len %d\n", __func__,
  32. (unsigned long long)timestamp, (int)len);
  33. lwsl_hexdump_notice(buf, len);
  34. #endif
  35. ok++;
  36. return 0;
  37. }
  38. static int
  39. smd_cb2int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
  40. void *buf, size_t len)
  41. {
  42. #if 0
  43. lwsl_notice("%s: ts %llu, len %d\n", __func__,
  44. (unsigned long long)timestamp, (int)len);
  45. lwsl_hexdump_notice(buf, len);
  46. #endif
  47. ok++;
  48. return 0;
  49. }
  50. static void *
  51. _thread_spam(void *d)
  52. {
  53. int n;
  54. n = 0;
  55. while (n++ < 100) {
  56. if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE,
  57. "{\"s\":\"state\",\"msg\":%d}",
  58. (unsigned int)n)) {
  59. lwsl_info("%s: send failed\n", __func__);
  60. n--;
  61. }
  62. #if defined(WIN32)
  63. Sleep(3);
  64. #else
  65. usleep(3000);
  66. #endif
  67. }
  68. #if !defined(WIN32)
  69. pthread_exit(NULL);
  70. #endif
  71. return NULL;
  72. }
  73. void sigint_handler(int sig)
  74. {
  75. interrupted = 1;
  76. }
  77. static int
  78. system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link,
  79. int current, int target)
  80. {
  81. // struct lws_context *context = mgr->parent;
  82. if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL)
  83. return 0;
  84. lwsl_info("%s: operational\n", __func__);
  85. /*
  86. * spawn the test thread, it's going to spam 100 messages at 20ms
  87. * intervals... check we got everything
  88. */
  89. if (pthread_create(&thread_spam, NULL, _thread_spam, NULL))
  90. lwsl_err("%s: failed to create the spamming thread\n", __func__);
  91. return 0;
  92. }
  93. int
  94. main(int argc, const char **argv)
  95. {
  96. lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" };
  97. lws_state_notify_link_t *na[] = { &notifier, NULL };
  98. int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
  99. struct lws_context_creation_info info;
  100. const char *p;
  101. void *retval;
  102. /* the normal lws init */
  103. signal(SIGINT, sigint_handler);
  104. if ((p = lws_cmdline_option(argc, argv, "-d")))
  105. logs = atoi(p);
  106. lws_set_log_level(logs, NULL);
  107. lwsl_user("LWS API selftest: lws_smd\n");
  108. memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
  109. info.port = CONTEXT_PORT_NO_LISTEN;
  110. info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
  111. info.register_notifier_list = na;
  112. context = lws_create_context(&info);
  113. if (!context) {
  114. lwsl_err("lws init failed\n");
  115. return 1;
  116. }
  117. lws_sul_schedule(context, 0, &sul, timeout_cb, 5 * LWS_US_PER_SEC);
  118. /* register a messaging participant to hear INTERACTION class */
  119. if (!lws_smd_register(context, NULL, 0, LWSSMDCL_INTERACTION,
  120. smd_cb1int)) {
  121. lwsl_err("%s: smd register 1 failed\n", __func__);
  122. goto bail;
  123. }
  124. /* register a messaging participant to hear SYSTEM_STATE class */
  125. if (!lws_smd_register(context, NULL, 0, LWSSMDCL_SYSTEM_STATE,
  126. smd_cb2int)) {
  127. lwsl_err("%s: smd register 2 failed\n", __func__);
  128. goto bail;
  129. }
  130. /* generate an INTERACTION class message */
  131. if (lws_smd_msg_printf(context, LWSSMDCL_INTERACTION,
  132. "{\"s\":\"interaction\"}")) {
  133. lwsl_err("%s: problem sending smd\n", __func__);
  134. goto bail;
  135. }
  136. /* generate a SYSTEM_STATE class message */
  137. if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE,
  138. "{\"s\":\"state\"}")) {
  139. lwsl_err("%s: problem sending smd\n", __func__);
  140. goto bail;
  141. }
  142. /* no participant listens for this class, so it should be skipped */
  143. if (lws_smd_msg_printf(context, LWSSMDCL_NETWORK, "{\"s\":\"network\"}")) {
  144. lwsl_err("%s: problem sending smd\n", __func__);
  145. goto bail;
  146. }
  147. /* the usual lws event loop */
  148. while (!interrupted && lws_service(context, 0) >= 0)
  149. ;
  150. pthread_join(thread_spam, &retval);
  151. bail:
  152. lws_context_destroy(context);
  153. if (fail || ok >= _exp)
  154. lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp,
  155. fail);
  156. else
  157. lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp);
  158. return !(ok >= _exp && !fail);
  159. }