| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- #include <unistd.h>
- #include <err.h>
- #include <errno.h>
- #include <pthread.h>
- #include <pthread_np.h>
- #include <sys/types.h>
- #include <sys/mman.h>
- #include <sys/socket.h>
- #include <netinet/in.h> /* bind */
- #include <fcntl.h> // O_xxxx
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h> //bzero
- static const char* pathname="/tmp/rats";
- /*
- * nc -u 127.0.0.1 5514
- */
- static void *udpController(void *dummy __attribute__((unused)))
- {
- /*
- *
- * block SIGINT
- * to make sure this signal
- * will be handled by the main thread
- * because this is this thread's way to terminate
- * the process
- *
- */
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGINT);
- if(sigprocmask(SIG_BLOCK, &sigmask, NULL))
- perror("sigprocmask");
- /*
- *
- * create share memory segment
- *
- */
- // may use SHM_ANON running FreeBSD while called by the same process
- int fd = shm_open(pathname, O_RDWR, 0600);
- if (fd < 0) {
- warn("%s: shm_open", __func__);
- pthread_exit(NULL);
- }
- if (ftruncate(fd, getpagesize()) < 0) {
- warn("%s: ftruncate", __func__);
- pthread_exit(NULL);
- }
- /*
- *
- * open an UDP socket
- *
- */
- int s = socket(PF_INET,SOCK_DGRAM, 0);
- if (-1 == s) {
- warn("socket");
- pthread_exit(NULL);
- }
- /*
- * Socket address, internet style.
- */
- struct sockaddr_in sa;
- bzero(&sa, sizeof sa);
- sa.sin_len = sizeof sa;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(5514);
- //sa.sin_addr.s_addr = htonl((((((127 << 8) | 0) << 8) | 0) << 8) | 1);
- sa.sin_addr.s_addr = INADDR_ANY;
- uint32_t cursor;
- if(!bind(s, (struct sockaddr *)&sa, sizeof sa)) {
- for(;;) {
- char buffer[getpagesize()];
- int n = read(s,&buffer[4], getpagesize()-4);
- if (n == -1) {
- break;
- }
- if (n > 0 ) {
- if(!bcmp((char *)&buffer[4], "quit", 4)) {
- printf("kill request\n");
- /* bye */
- kill(getpid(), SIGINT);
- break;
- }
- /* prepend length into the buffer */
- cursor = n + 4;
- buffer[0] = (n >> 24);
- buffer[1] = (n >> 16);
- buffer[2] = (n>> 8);
- buffer[3] = (n);
- ssize_t len = pwrite(fd, buffer, cursor, 0);
- if (len < 0) {
- warn("%s: pwrite failure", __func__);
- }
- if (len != cursor) {
- warn("%zu vs %du, %s: pwrite length mismatch",len,cursor, __func__);
- }
- }
- }
- } else
- warn("bind failure");
- close (s);
- pthread_exit(NULL);
- }
- static void showmem()
- {
- int fd = shm_open(pathname, O_RDONLY, 0600);
- if (fd < 0) {
- warn("%s: shm_open", __func__);
- return;
- }
- /* extract length */
- uint8_t curbuf[4];
- ssize_t len = pread(fd, &curbuf, 4, 0);
- if (len == 4) {
- uint32_t l = (uint32_t)curbuf[0] << 24 |
- (uint32_t)curbuf[1] << 16 |
- (uint32_t)curbuf[2] << 8 |
- (uint32_t)curbuf[3];
- if (l > 0) {
- uint8_t* buf = malloc(l);
- if (buf) {
- /* data */
- ssize_t total = pread(fd, buf, l, 4);
- printf("%zu:\t %s", total, buf);
- free(buf);
- } else {
- warn("malloc");
- }
- }
- } else {
- printf("nothing.\n");
- }
- }
- static void
- sigHandler(int signo, siginfo_t *si, void * /* ucontext_t */ uap)
- {
- switch (signo) {
- case SIGINFO:
- printf("no need to panic.\n");
- __attribute__((fallthrough));
- case SIGALRM:
- showmem();
- break;
- default:
- printf("sig:%d received.", signo);
- break;
- }
- }
- int main(int argc, char* argv[])
- {
- timer_t timerid;
- int fd = shm_open(pathname, O_CREAT | O_RDWR, 0600);
- if (fd < 0)
- err(EXIT_FAILURE, "%s: shm_open", __func__);
- if (ftruncate(fd, getpagesize()) < 0)
- err(EXIT_FAILURE, "%s: ftruncate", __func__);
- pthread_t pidudp;
- pthread_create(&pidudp, NULL, &udpController, NULL);
- /* signal */
- struct sigaction sa;
- sa.sa_handler = NULL;
- sa.sa_sigaction = &sigHandler;
- sa.sa_flags = SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
- // Block every signal during the handler
- sigfillset(&sa.sa_mask);
- if (sigaction(SIGINFO, &sa, NULL)) {
- warn("SIGNFO not caught.");
- }
- if (sigaction(SIGALRM, &sa, NULL)) {
- err(EXIT_FAILURE, "sigaction:ALARM");
- }
- /* timer */
- if (timer_create(CLOCK_REALTIME, NULL, &timerid)) {
- err(EXIT_FAILURE,"timer_create failed.");
- }
- /* 3 -> TIMER_MAX stored into timerid->oshandle */
- printf("Timer #%d now created at address %p.\n", timer_oshandle_np(timerid), timerid);
- /* Set values and start timer */
- struct itimerspec its;
- its.it_interval.tv_sec = 2;
- its.it_interval.tv_nsec = 0;
- its.it_value.tv_sec = its.it_interval.tv_sec;
- its.it_value.tv_nsec = 0;
- if (timer_settime(timerid, 0, &its, NULL)) {
- warn("timer_settime failed.");
- }
- printf("waiting...\n");
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask,SIGINT);
- sigprocmask(SIG_BLOCK,&sigmask,NULL);
- int sigpending;
- if (sigwait(&sigmask, &sigpending))
- warn("sigwait failure.\n");
- //brutal thread killing, I know it s bad. but I 'm punk btw.
- printf("bye\n");
- timer_delete(timerid);
- struct timespec t;
- if (!clock_gettime(CLOCK_REALTIME, &t)) {
- t.tv_sec += 5;
- if (pthread_timedjoin_np(pidudp, NULL, &t)) {
- pthread_cancel(pidudp);
- }
- } else {
- warn("clock_gettime");
- }
- // required until SHM_ANON is used, or shm remains (persistent until reboot)
- shm_unlink(pathname);
- return EXIT_SUCCESS;
- }
|