Skip to content

Instantly share code, notes, and snippets.

@EBADBEEF
Created April 14, 2024 02:39
Show Gist options
  • Save EBADBEEF/39a106bbe48498e6647fdb698aaab9b6 to your computer and use it in GitHub Desktop.
Save EBADBEEF/39a106bbe48498e6647fdb698aaab9b6 to your computer and use it in GitHub Desktop.
#include <arpa/inet.h>
#include <semaphore.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
enum log_level {
LOG_FATAL,
LOG_MSG,
LOG_DEBUG
};
enum log_level global_log_level = LOG_MSG;
void log_print(enum log_level lvl, const char *fmt, ...)
{
va_list args;
if (lvl > global_log_level) {
return;
}
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
if (lvl == LOG_FATAL) {
exit(EXIT_FAILURE);
}
}
#define fatal(fmt, args...) log_print(LOG_FATAL, fmt, ##args)
#define msg(fmt, args...) log_print(LOG_MSG, fmt, ##args)
#define debug(fmt, args...) log_print(LOG_DEBUG, fmt, ##args)
int main(int argc, char **argv)
{
const char *host = "224.0.2.60";
const uint16_t port = 4445;
const int wakeup_seconds = 2;
sem_t wake = {0};
struct sockaddr_in addr = {0};
//const uint8_t buf[] = "[MOTD]Home server[/MOTD][AD]25565[/AD]";
//const size_t buflen = sizeof(buf);
char *buf;
size_t buflen;
struct timespec ts;
int ret;
if (getenv("DEBUG") != NULL) {
global_log_level = LOG_DEBUG;
}
if (argc != 2) {
fatal("usage: minecraft-announce \"[MOTD]A motd here[/MOTD][AD]<port number, e.g. 25565>[/AD]\"");
}
buf = argv[1];
/* include the '\0' in the length */
buflen = strlen(buf)+1;
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
fatal("socket failed errno %d (%s)", errno, strerror(errno));
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
ret = inet_pton(AF_INET, host, &addr.sin_addr);
if (ret != 1) {
close(sockfd);
fatal("inet_pton failed errno %d (%s)", errno, strerror(errno));
}
clock_gettime(CLOCK_REALTIME, &ts);
msg("sending \"%s\" to %s:%d every %d seconds",
buf, host, port, wakeup_seconds);
/* turn final '\0' into '\n' */
buf[buflen-1] = '\n';
while(1) {
ret = sendto(sockfd, buf, buflen, 0, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
fatal("sendto failed errno %d (%s)", errno, strerror(errno));
}
debug("sent %d/%d bytes to %s:%d", ret, buflen, host, port);
ts.tv_sec += 2;
ret = sem_timedwait(&wake, &ts);
if (ret < 0 && errno != ETIMEDOUT) {
fatal("sem_timedwait");
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment