1161030Ssam/*-
2161030Ssam * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3161030Ssam * All rights reserved.
4161030Ssam *
5161030Ssam * Redistribution and use in source and binary forms, with or without
6161030Ssam * modification, are permitted provided that the following conditions
7161030Ssam * are met:
8161030Ssam * 1. Redistributions of source code must retain the above copyright
9161030Ssam *    notice, this list of conditions and the following disclaimer.
10161030Ssam * 2. Redistributions in binary form must reproduce the above copyright
11161030Ssam *    notice, this list of conditions and the following disclaimer in the
12161030Ssam *    documentation and/or other materials provided with the distribution.
13161030Ssam *
14161030Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15161030Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16161030Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17161030Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18161030Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19161030Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20161030Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21161030Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22161030Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23161030Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24161030Ssam * SUCH DAMAGE.
25161030Ssam *
26161030Ssam * $FreeBSD$
27161030Ssam */
28161030Ssam#include <sys/types.h>
29161030Ssam#include <sys/socket.h>
30161030Ssam#include <sys/select.h>
31161030Ssam#include <sys/time.h>
32161030Ssam#include <netinet/in.h>
33161030Ssam#include <arpa/inet.h>
34161030Ssam#include <stdio.h>
35161030Ssam#include <unistd.h>
36161030Ssam#include <stdlib.h>
37161030Ssam#include <string.h>
38161030Ssam#include <assert.h>
39161030Ssam#include <time.h>
40161030Ssam#include <err.h>
41161030Ssam
42161030Ssamint poll_rate = 5;
43161030Ssamint pps = 10;
44161030Ssam
45161030Ssam//#define INSANE
46161030Ssam
47161030Ssamvoid own(int s, struct sockaddr_in* s_in) {
48161030Ssam	char buf[64];
49161030Ssam	int times = 10;
50161030Ssam	int i;
51161030Ssam	int delay = 10*1000;
52161030Ssam	unsigned int sent = 0;
53161030Ssam	struct timeval start, end;
54161030Ssam	struct timespec ts;
55161030Ssam	int dont_sleep_times = 1;
56161030Ssam	int dont_sleep;
57161030Ssam
58161030Ssam	delay = (int) ((double)1.0/pps*1000.0*1000.0);
59161030Ssam
60161030Ssam	if (delay <= 5000) {
61161030Ssam		dont_sleep_times = 10;
62161030Ssam/*
63161030Ssam		printf("delay is %d... sleeping every %d packets\n",
64161030Ssam			delay, dont_sleep_times);
65161030Ssam*/
66161030Ssam		delay *= dont_sleep_times;
67161030Ssam
68161030Ssam		delay = (int) (0.90*delay);
69161030Ssam	}
70161030Ssam
71161030Ssam	dont_sleep = dont_sleep_times;
72161030Ssam	times = poll_rate*pps;
73161030Ssam//	times *= dont_sleep;
74161030Ssam
75161030Ssam
76161030Ssam
77161030Ssam	ts.tv_sec = 0;
78161030Ssam	ts.tv_nsec = delay*1000;
79161030Ssam
80161030Ssam//	printf("times=%d delay=%d\n", times, delay);
81161030Ssam	if (gettimeofday(&start, NULL) == -1) {
82161030Ssam		perror("gettimeofday()");
83161030Ssam		exit(1);
84161030Ssam	}
85161030Ssam
86161030Ssam	for(i = 0; i < times; i++) {
87161030Ssam		if( sendto(s, buf, 6, 0, (struct sockaddr *)s_in, sizeof(*s_in)) != 6) {
88161030Ssam			printf("messed up a bit\n");
89161030Ssam			return;
90161030Ssam		}
91161030Ssam
92161030Ssam#ifndef INSANE
93161030Ssam
94161030Ssam#if 0
95161030Ssam		if (usleep(delay) == -1) {
96161030Ssam			perror("usleep()");
97161030Ssam			exit(1);
98161030Ssam		}
99161030Ssam#endif
100161030Ssam		dont_sleep--;
101161030Ssam
102161030Ssam		if (!dont_sleep) {
103161030Ssam			if (nanosleep(&ts, NULL) == -1) {
104161030Ssam				perror("nanosleep()");
105161030Ssam				exit(1);
106161030Ssam			}
107161030Ssam
108161030Ssam			dont_sleep  = dont_sleep_times;
109161030Ssam		}
110161030Ssam
111161030Ssam#endif
112161030Ssam		sent++;
113161030Ssam	}
114161030Ssam
115161030Ssam	if (gettimeofday(&end, NULL) == -1) {
116161030Ssam		perror("gettimeofday()");
117161030Ssam		exit(1);
118161030Ssam	}
119161030Ssam
120161030Ssam	printf ("Sent %.03f p/s\n", ((double)sent)/(((double)end.tv_sec) - start.tv_sec));
121161030Ssam
122161030Ssam//	printf("Sent %d packets\n", i);
123161030Ssam}
124161030Ssam
125161030Ssamint main(int argc, char* argv[]) {
126161030Ssam	int port = 6969;
127161030Ssam	struct sockaddr_in s_in;
128161030Ssam	int s;
129161030Ssam	int rd;
130161030Ssam	int len;
131161030Ssam	char buf[64];
132161030Ssam	struct timeval tv;
133161030Ssam	int do_it = 0;
134161030Ssam	fd_set rfds;
135161030Ssam	char ip[17];
136161030Ssam
137161030Ssam	if( argc > 1)
138161030Ssam		pps = atoi(argv[1]);
139161030Ssam
140161030Ssam	printf("Packets per second=%d\n", pps);
141161030Ssam
142161030Ssam	s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
143161030Ssam	if( s < 0)
144161030Ssam		err(1, "socket()");
145161030Ssam
146161030Ssam	s_in.sin_family = PF_INET;
147161030Ssam	s_in.sin_port = htons(port);
148161030Ssam	s_in.sin_addr.s_addr = INADDR_ANY;
149161030Ssam
150161030Ssam	if( bind(s, (struct sockaddr*)&s_in, sizeof(s_in)) < 0) {
151161030Ssam		perror("bind()");
152161030Ssam		exit(1);
153161030Ssam	}
154161030Ssam
155161030Ssam	while(1) {
156161030Ssam		assert(do_it >= 0);
157161030Ssam		len = sizeof(struct sockaddr_in);
158161030Ssam
159161030Ssam		memset(&tv, 0, sizeof(tv));
160161030Ssam		tv.tv_usec = 1000*10;
161161030Ssam		FD_ZERO(&rfds);
162161030Ssam		FD_SET(s, &rfds);
163161030Ssam		rd = select(s + 1, &rfds, NULL ,NULL ,&tv);
164161030Ssam		if (rd == -1) {
165161030Ssam			perror("select()");
166161030Ssam			exit(1);
167161030Ssam		}
168161030Ssam		if (rd == 1 && FD_ISSET(s, &rfds)) {
169161030Ssam			rd = recvfrom(s, buf, 64, 0, (struct sockaddr*)&s_in, &len);
170161030Ssam
171161030Ssam			if(rd < 0) {
172161030Ssam				perror("read died");
173161030Ssam				exit(1);
174161030Ssam			}
175161030Ssam
176161030Ssam			if(rd == 5 && memcmp(buf, "sorbo", 5) == 0) {
177161030Ssam				sprintf(ip, "%s", inet_ntoa(s_in.sin_addr));
178161030Ssam				printf("Got signal from %s\n", ip);
179161030Ssam#ifdef INSANE
180161030Ssam				do_it = 10;
181161030Ssam#else
182161030Ssam				do_it = 2;
183161030Ssam#endif
184161030Ssam			}
185161030Ssam		}
186161030Ssam
187161030Ssam		if (do_it) {
188161030Ssam			printf("Sending stuff to %s\n", ip);
189161030Ssam
190161030Ssam			own(s, &s_in);
191161030Ssam			do_it--;
192161030Ssam
193161030Ssam			if(do_it == 0)
194161030Ssam			printf("Stopping send\n");
195161030Ssam		}
196161030Ssam	}
197161030Ssam}
198