1/*
2 * Copyright 2010, Atis Elsts, the.kfx@gmail.com
3 * Distributed under the terms of the MIT license.
4 */
5
6
7#include <unistd.h>
8#include <memory.h>
9#include <netinet/in.h>
10#include <netinet/ip.h>
11#include <arpa/inet.h>
12#include <errno.h>
13#include <stdio.h>
14#include <stdlib.h>
15
16
17const unsigned short TEST_PORT = 40000;
18
19
20void
21recvLoop(int fd)
22{
23	for (;;) {
24		char buffer[1000];
25		sockaddr_storage address;
26		socklen_t socklen = sizeof(address);
27		memset(&address, 0, socklen);
28
29		int status = recvfrom(fd, buffer, sizeof(buffer) - 1, 0,
30			(sockaddr *) &address, &socklen);
31		if (status < 0) {
32			perror("recvfrom");
33			exit(-1);
34		}
35		if (status == 0) {
36			printf("received EOF!\n");
37			break;
38		} else {
39			buffer[status] = 0;
40			printf("received %d bytes: \"%s\"\n", status, buffer);
41		}
42	}
43}
44
45
46int
47main(int argc, char *argv[])
48{
49	int socketFamily = AF_INET;
50
51	if (argc > 1) {
52		if (!strcmp(argv[1], "-4"))
53			socketFamily = AF_INET;
54		else if (!strcmp(argv[1], "-6"))
55			socketFamily = AF_INET6;
56	}
57
58	int fd = socket(socketFamily, SOCK_DGRAM, 0);
59	if (fd < 0) {
60		perror("socket");
61		return -1;
62	}
63
64	sockaddr_storage localAddress;
65	memset(&localAddress, 0, sizeof(localAddress));
66	if (socketFamily == AF_INET) {
67		sockaddr_in *sa = (sockaddr_in *) &localAddress;
68		sa->sin_family = AF_INET;
69		sa->sin_port = htons(TEST_PORT);
70	} else {
71		sockaddr_in6 *sa = (sockaddr_in6 *) &localAddress;
72		sa->sin6_family = AF_INET6;
73		sa->sin6_port = htons(TEST_PORT);
74		// loopback
75		sa->sin6_addr.s6_addr[15] = 0x01;
76	}
77
78	if (bind(fd, (sockaddr *)&localAddress, socketFamily == AF_INET ?
79			sizeof(sockaddr_in) : sizeof(sockaddr_in6)) < 0) {
80		perror("bind");
81		return -1;
82	}
83
84	for (;;)
85		recvLoop(fd);
86}
87