main.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include <unistd.h>
  2. #include <err.h>
  3. #include <errno.h>
  4. #include <pthread.h>
  5. #include <pthread_np.h>
  6. #include <sys/types.h>
  7. #include <sys/mman.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h> /* bind */
  10. #include <fcntl.h> // O_xxxx
  11. #include <signal.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h> //bzero
  15. #include <malloc_np.h>
  16. static const char* pathname="/tmp/rats";
  17. /*
  18. * nc -u 127.0.0.1 5514
  19. */
  20. static void *udpController(void *dummy __attribute__((unused)))
  21. {
  22. /*
  23. *
  24. * block SIGINT
  25. * to make sure this signal
  26. * will be handled by the main thread
  27. * because this is this thread's way to terminate
  28. * the process
  29. *
  30. */
  31. sigset_t sigmask;
  32. sigemptyset(&sigmask);
  33. sigaddset(&sigmask, SIGINT);
  34. if(sigprocmask(SIG_BLOCK, &sigmask, NULL))
  35. perror("sigprocmask");
  36. /*
  37. *
  38. * create share memory segment
  39. *
  40. */
  41. // may use SHM_ANON running FreeBSD while called by the same process
  42. int fd = shm_open(pathname, O_RDWR, 0600);
  43. if (fd < 0) {
  44. warn("%s: shm_open", __func__);
  45. pthread_exit(NULL);
  46. }
  47. if (ftruncate(fd, getpagesize()) < 0) {
  48. warn("%s: ftruncate", __func__);
  49. pthread_exit(NULL);
  50. }
  51. /*
  52. *
  53. * open an UDP socket
  54. *
  55. */
  56. int s = socket(PF_INET,SOCK_DGRAM, 0);
  57. if (-1 == s) {
  58. warn("socket");
  59. pthread_exit(NULL);
  60. }
  61. /*
  62. * Socket address, internet style.
  63. */
  64. struct sockaddr_in sa;
  65. bzero(&sa, sizeof sa);
  66. sa.sin_len = sizeof sa;
  67. sa.sin_family = AF_INET;
  68. sa.sin_port = htons(5514);
  69. //sa.sin_addr.s_addr = htonl((((((127 << 8) | 0) << 8) | 0) << 8) | 1);
  70. sa.sin_addr.s_addr = INADDR_ANY;
  71. uint32_t cursor;
  72. if(!bind(s, (struct sockaddr *)&sa, sizeof sa)) {
  73. for(;;) {
  74. char buffer[getpagesize()];
  75. int n = read(s,&buffer[4], getpagesize()-4);
  76. if (n == -1) {
  77. break;
  78. }
  79. if (n > 0 ) {
  80. if(!bcmp((char *)&buffer[4], "quit", 4)) {
  81. printf("kill request\n");
  82. /* bye */
  83. kill(getpid(), SIGINT);
  84. break;
  85. }
  86. /* prepend length into the buffer */
  87. cursor = n + 4;
  88. buffer[0] = (n >> 24);
  89. buffer[1] = (n >> 16);
  90. buffer[2] = (n>> 8);
  91. buffer[3] = (n);
  92. ssize_t len = pwrite(fd, buffer, cursor, 0);
  93. if (len < 0) {
  94. warn("%s: pwrite failure", __func__);
  95. }
  96. if (len != cursor) {
  97. warn("%zu vs %du, %s: pwrite length mismatch",len,cursor, __func__);
  98. }
  99. }
  100. }
  101. } else
  102. warn("bind failure");
  103. close (s);
  104. pthread_exit(NULL);
  105. }
  106. static void showmem()
  107. {
  108. int fd = shm_open(pathname, O_RDONLY, 0600);
  109. if (fd < 0) {
  110. warn("%s: shm_open", __func__);
  111. return;
  112. }
  113. /* extract length */
  114. uint8_t curbuf[4];
  115. ssize_t len = pread(fd, &curbuf, 4, 0);
  116. if (len == 4) {
  117. uint32_t l = (uint32_t)curbuf[0] << 24 |
  118. (uint32_t)curbuf[1] << 16 |
  119. (uint32_t)curbuf[2] << 8 |
  120. (uint32_t)curbuf[3];
  121. if (l > 0) {
  122. uint8_t *buf = mallocx(l, MALLOCX_ZERO);
  123. if (buf) {
  124. /* data */
  125. ssize_t total = pread(fd, buf, l, 4);
  126. printf("%zu:\t %s", total, buf);
  127. free(buf);
  128. } else {
  129. warn("malloc");
  130. }
  131. }
  132. } else {
  133. printf("nothing.\n");
  134. }
  135. }
  136. static void
  137. sigHandler(int signo, siginfo_t *si, void * /* ucontext_t */ uap)
  138. {
  139. switch (signo) {
  140. case SIGINFO:
  141. printf("no need to panic.\n");
  142. __attribute__((fallthrough));
  143. case SIGALRM:
  144. showmem();
  145. break;
  146. default:
  147. printf("sig:%d received.", signo);
  148. break;
  149. }
  150. }
  151. int main(int argc, char* argv[])
  152. {
  153. timer_t timerid;
  154. int fd = shm_open(pathname, O_CREAT | O_RDWR, 0600);
  155. if (fd < 0)
  156. err(EXIT_FAILURE, "%s: shm_open", __func__);
  157. if (ftruncate(fd, getpagesize()) < 0)
  158. err(EXIT_FAILURE, "%s: ftruncate", __func__);
  159. pthread_t pidudp;
  160. pthread_create(&pidudp, NULL, &udpController, NULL);
  161. /* signal */
  162. struct sigaction sa;
  163. sa.sa_handler = NULL;
  164. sa.sa_sigaction = &sigHandler;
  165. sa.sa_flags = SA_SIGINFO;
  166. sigemptyset(&sa.sa_mask);
  167. // Block every signal during the handler
  168. sigfillset(&sa.sa_mask);
  169. if (sigaction(SIGINFO, &sa, NULL)) {
  170. warn("SIGNFO not caught.");
  171. }
  172. if (sigaction(SIGALRM, &sa, NULL)) {
  173. err(EXIT_FAILURE, "sigaction:ALARM");
  174. }
  175. /* timer */
  176. if (timer_create(CLOCK_REALTIME, NULL, &timerid)) {
  177. err(EXIT_FAILURE,"timer_create failed.");
  178. }
  179. /* 3 -> TIMER_MAX stored into timerid->oshandle */
  180. printf("Timer #%d now created at address %p.\n", timer_oshandle_np(timerid), timerid);
  181. /* Set values and start timer */
  182. struct itimerspec its;
  183. its.it_interval.tv_sec = 2;
  184. its.it_interval.tv_nsec = 0;
  185. its.it_value.tv_sec = its.it_interval.tv_sec;
  186. its.it_value.tv_nsec = 0;
  187. if (timer_settime(timerid, 0, &its, NULL)) {
  188. warn("timer_settime failed.");
  189. }
  190. printf("waiting...\n");
  191. sigset_t sigmask;
  192. sigemptyset(&sigmask);
  193. sigaddset(&sigmask,SIGINT);
  194. sigprocmask(SIG_BLOCK,&sigmask,NULL);
  195. int sigpending;
  196. if (sigwait(&sigmask, &sigpending))
  197. warn("sigwait failure.\n");
  198. //brutal thread killing, I know it s bad. but I 'm punk btw.
  199. printf("bye\n");
  200. timer_delete(timerid);
  201. struct timespec t;
  202. if (!clock_gettime(CLOCK_REALTIME, &t)) {
  203. t.tv_sec += 5;
  204. if (pthread_timedjoin_np(pidudp, NULL, &t)) {
  205. pthread_cancel(pidudp);
  206. }
  207. } else {
  208. warn("clock_gettime");
  209. }
  210. // required until SHM_ANON is used, or shm remains (persistent until reboot)
  211. shm_unlink(pathname);
  212. return EXIT_SUCCESS;
  213. }