/* IPv4 broadcasting example.
 * (there's no broadcast in IPv6, only multicast/anycast.)
 *
 * Copyright (c) 2008, Andreas Henriksson <andreas@fatal.se>
 * License: WTFPLv2.
 */

#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <stdlib.h> /* malloc */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */

#include <arpa/inet.h> /* inet_pton */

/* source */
#define BROADCAST_IFADDR "0.0.0.0" /* any */
#define BROADCAST_SERVICE NULL /* any */

/* destination */
#define BROADCAST_TOADDR "255.255.255.255" /* everyone */
#define BROADCAST_TOSERVICE "54321"

void debug_socket (struct sockaddr *sa, int sa_len)
{
	int err;
	char host[NI_MAXHOST], serv[NI_MAXSERV];

	err = getnameinfo (sa, sa_len, host, NI_MAXHOST, serv, NI_MAXSERV,
			NI_NUMERICHOST);
	printf("DEBUG: host=%s, serv=%s\n", host, serv);
}

void init_broadcast (struct sockaddr **sa, int *salen)
{
	struct addrinfo hints, *res;
	int err;

	bzero(&hints, sizeof(hints));
	hints.ai_family = AF_INET;

	err = getaddrinfo(BROADCAST_TOADDR, BROADCAST_TOSERVICE, &hints, &res);
	if (err)
		perror("getaddrinfo");

	*salen = res->ai_addrlen;

	*sa = malloc(*salen);
	memcpy(*sa, res->ai_addr, *salen);

	freeaddrinfo(res);

	debug_socket(*sa, *salen);
}

int createudpsocket (char *host, char *service)
{
	struct addrinfo hints, *res, *curr;
	int err, fd;

	memset (&hints, '\0', sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_protocol = IPPROTO_UDP;
	hints.ai_flags = AI_PASSIVE;


	err = getaddrinfo(host, service, &hints, &res);

	for (curr = res; curr != NULL; curr = curr->ai_next) {
		fd = socket (curr->ai_family, curr->ai_socktype,
				curr->ai_protocol);
		if (fd < 0)
			continue;

#if 0
		err = bind (fd, curr->ai_addr, curr->ai_addrlen);
		if (err)
			continue;
#endif

		debug_socket(curr->ai_addr, curr->ai_addrlen);

		break;
	}

	if (curr == NULL)
		fprintf(stderr, "WARN: unable to create udp socket.\n");

	freeaddrinfo(res);

	return fd;
}

int main (int argc, char **argv)
{
	int fd;
	int on = 1;
	char buf[] = "broadcasting foobar\n";
	struct sockaddr *sa;
	int salen;

	/* create socket */
	fd = createudpsocket(BROADCAST_IFADDR, BROADCAST_SERVICE);

	/* allow broadcast messages */
	if (setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)))
		perror("setsockopt");

	/* look up broadcast address */
	init_broadcast(&sa, &salen);
	

	/* loop */
	while (1) {
		int err;

		err = sendto(fd, buf, strlen(buf), 0 /* flags */,
				sa, salen);

		if (err < 0)
			perror("sendto");
		else
			printf("DEBUG: sent %d bytes.\n", err);

		sleep(2);
	}


	return 0;
}


