main.c 5.1 KB

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