1 /* Simulate a server with connections of different speeds. We count
2 * how many connections complete in 10 seconds. */
3 #include <ccan/io/io.h>
4 #include <ccan/time/time.h>
5 #include <ccan/err/err.h>
7 #include <sys/socket.h>
17 #define REQUEST_MAX 131072
18 #define NUM_CONNS 500 /* per child */
19 #define NUM_CHILDREN 2
21 static unsigned int completed;
28 static struct io_plan write_reply(struct io_conn *conn, struct client *client);
29 static struct io_plan read_body(struct io_conn *conn, struct client *client)
31 assert(client->len <= REQUEST_MAX);
32 return io_read(client->request_buffer, client->len,
36 static struct io_plan io_read_header(struct client *client)
38 return io_read(&client->len, sizeof(client->len), read_body, client);
41 /* once we're done, loop again. */
42 static struct io_plan write_complete(struct io_conn *conn, struct client *client)
45 return io_read_header(client);
48 static struct io_plan write_reply(struct io_conn *conn, struct client *client)
50 return io_write(&client->len, sizeof(client->len),
51 write_complete, client);
54 /* This runs in the child. */
55 static void create_clients(struct sockaddr_un *addr, int waitfd)
58 int i, sock[NUM_CONNS], len[NUM_CONNS], done[NUM_CONNS],
59 result[NUM_CONNS], count = 0;
61 for (i = 0; i < NUM_CONNS; i++) {
62 len[i] = (random() % REQUEST_MAX) + 1;
63 sock[i] = socket(AF_UNIX, SOCK_STREAM, 0);
65 err(1, "creating socket");
66 if (connect(sock[i], (void *)addr, sizeof(*addr)) != 0)
67 err(1, "connecting socket");
68 /* Make nonblocking. */
69 fcntl(sock[i], F_SETFD, fcntl(sock[i], F_GETFD)|O_NONBLOCK);
76 for (i = 0; i < NUM_CONNS; i++) {
77 int ret, totlen = len[i] + sizeof(len[i]);
78 if (done[i] < sizeof(len[i]) + len[i]) {
80 ret = write(sock[i], (void *)&data + done[i],
84 else if (ret < 0 && errno != EAGAIN)
87 int off = done[i] - totlen;
88 ret = read(sock[i], (void *)&result[i] + off,
89 sizeof(result[i]) - off);
93 + sizeof(result[i])) {
94 assert(result[i] == len[i]);
98 } else if (ret < 0 && errno != EAGAIN)
104 printf("Child did %u\n", count);
108 static int timeout[2];
109 static void sigalarm(int sig)
111 write(timeout[1], "1", 1);
114 static struct io_plan do_timeout(struct io_conn *conn, char *buf)
116 return io_break(buf, io_idle());
119 int main(int argc, char *argv[])
122 struct sockaddr_un addr;
123 struct timespec start, end;
124 char buffer[REQUEST_MAX];
128 addr.sun_family = AF_UNIX;
129 sprintf(addr.sun_path, "/tmp/run-different-speed.sock.%u", getpid());
131 if (pipe(wake) != 0 || pipe(timeout) != 0)
132 err(1, "Creating pipes");
134 fd = socket(AF_UNIX, SOCK_STREAM, 0);
136 err(1, "Creating socket");
138 if (bind(fd, (void *)&addr, sizeof(addr)) != 0)
139 err(1, "Binding to %s", addr.sun_path);
141 if (listen(fd, NUM_CONNS) != 0)
142 err(1, "Listening on %s", addr.sun_path);
144 for (i = 0; i < NUM_CHILDREN; i++) {
150 create_clients(&addr, wake[0]);
153 for (j = 0; j < NUM_CONNS; j++) {
154 struct client *client = malloc(sizeof(*client));
155 int ret = accept(fd, NULL, 0);
157 err(1, "Accepting fd");
158 /* For efficiency, we share buffer */
159 client->request_buffer = buffer;
160 io_new_conn(ret, io_read_header(client));
164 io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf));
167 for (i = 0; i < NUM_CHILDREN; i++)
168 write(wake[1], "1", 1);
170 signal(SIGALRM, sigalarm);
177 printf("%u connections complete (%u ns per conn)\n",
179 (int)time_to_nsec(time_divide(time_sub(end, start), completed)));