1/*-
2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/select.h>
29#include <sys/time.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <stdio.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <string.h>
36#include <assert.h>
37#include <time.h>
38#include <err.h>
39
40int poll_rate = 5;
41int pps = 10;
42
43//#define INSANE
44
45void own(int s, struct sockaddr_in* s_in) {
46	char buf[64];
47	int times = 10;
48	int i;
49	int delay = 10*1000;
50	unsigned int sent = 0;
51	struct timeval start, end;
52	struct timespec ts;
53	int dont_sleep_times = 1;
54	int dont_sleep;
55
56	delay = (int) ((double)1.0/pps*1000.0*1000.0);
57
58	if (delay <= 5000) {
59		dont_sleep_times = 10;
60/*
61		printf("delay is %d... sleeping every %d packets\n",
62			delay, dont_sleep_times);
63*/
64		delay *= dont_sleep_times;
65
66		delay = (int) (0.90*delay);
67	}
68
69	dont_sleep = dont_sleep_times;
70	times = poll_rate*pps;
71//	times *= dont_sleep;
72
73
74
75	ts.tv_sec = 0;
76	ts.tv_nsec = delay*1000;
77
78//	printf("times=%d delay=%d\n", times, delay);
79	if (gettimeofday(&start, NULL) == -1) {
80		perror("gettimeofday()");
81		exit(1);
82	}
83
84	for(i = 0; i < times; i++) {
85		if( sendto(s, buf, 6, 0, (struct sockaddr *)s_in, sizeof(*s_in)) != 6) {
86			printf("messed up a bit\n");
87			return;
88		}
89
90#ifndef INSANE
91
92#if 0
93		if (usleep(delay) == -1) {
94			perror("usleep()");
95			exit(1);
96		}
97#endif
98		dont_sleep--;
99
100		if (!dont_sleep) {
101			if (nanosleep(&ts, NULL) == -1) {
102				perror("nanosleep()");
103				exit(1);
104			}
105
106			dont_sleep  = dont_sleep_times;
107		}
108
109#endif
110		sent++;
111	}
112
113	if (gettimeofday(&end, NULL) == -1) {
114		perror("gettimeofday()");
115		exit(1);
116	}
117
118	printf ("Sent %.03f p/s\n", ((double)sent)/(((double)end.tv_sec) - start.tv_sec));
119
120//	printf("Sent %d packets\n", i);
121}
122
123int main(int argc, char* argv[]) {
124	int port = 6969;
125	struct sockaddr_in s_in;
126	int s;
127	int rd;
128	int len;
129	char buf[64];
130	struct timeval tv;
131	int do_it = 0;
132	fd_set rfds;
133	char ip[17];
134
135	if( argc > 1)
136		pps = atoi(argv[1]);
137
138	printf("Packets per second=%d\n", pps);
139
140	s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
141	if( s < 0)
142		err(1, "socket()");
143
144	s_in.sin_family = PF_INET;
145	s_in.sin_port = htons(port);
146	s_in.sin_addr.s_addr = INADDR_ANY;
147
148	if( bind(s, (struct sockaddr*)&s_in, sizeof(s_in)) < 0) {
149		perror("bind()");
150		exit(1);
151	}
152
153	while(1) {
154		assert(do_it >= 0);
155		len = sizeof(struct sockaddr_in);
156
157		memset(&tv, 0, sizeof(tv));
158		tv.tv_usec = 1000*10;
159		FD_ZERO(&rfds);
160		FD_SET(s, &rfds);
161		rd = select(s + 1, &rfds, NULL ,NULL ,&tv);
162		if (rd == -1) {
163			perror("select()");
164			exit(1);
165		}
166		if (rd == 1 && FD_ISSET(s, &rfds)) {
167			rd = recvfrom(s, buf, 64, 0, (struct sockaddr*)&s_in, &len);
168
169			if(rd < 0) {
170				perror("read died");
171				exit(1);
172			}
173
174			if(rd == 5 && memcmp(buf, "sorbo", 5) == 0) {
175				sprintf(ip, "%s", inet_ntoa(s_in.sin_addr));
176				printf("Got signal from %s\n", ip);
177#ifdef INSANE
178				do_it = 10;
179#else
180				do_it = 2;
181#endif
182			}
183		}
184
185		if (do_it) {
186			printf("Sending stuff to %s\n", ip);
187
188			own(s, &s_in);
189			do_it--;
190
191			if(do_it == 0)
192			printf("Stopping send\n");
193		}
194	}
195}
196