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_op *write_reply(struct io_conn *conn, struct client *client);
29 static struct io_op *read_body(struct io_conn *conn, struct client *client)
31 assert(client->len <= REQUEST_MAX);
32 return io_read(client->request_buffer, client->len,
33 io_next(conn, write_reply, client));
36 static struct io_op *read_header(struct io_conn *conn, struct client *client)
38 return io_read(&client->len, sizeof(client->len),
39 io_next(conn, read_body, client));
42 /* once we're done, loop again. */
43 static struct io_op *write_complete(struct io_conn *conn, struct client *client)
46 return read_header(conn, client);
49 static struct io_op *write_reply(struct io_conn *conn, struct client *client)
51 return io_write(&client->len, sizeof(client->len),
52 io_next(conn, write_complete, client));
55 /* This runs in the child. */
56 static void create_clients(struct sockaddr_un *addr, int waitfd)
59 int i, sock[NUM_CONNS], len[NUM_CONNS], done[NUM_CONNS],
60 result[NUM_CONNS], count = 0;
62 for (i = 0; i < NUM_CONNS; i++) {
63 len[i] = (random() % REQUEST_MAX) + 1;
64 sock[i] = socket(AF_UNIX, SOCK_STREAM, 0);
66 err(1, "creating socket");
67 if (connect(sock[i], (void *)addr, sizeof(*addr)) != 0)
68 err(1, "connecting socket");
69 /* Make nonblocking. */
70 fcntl(sock[i], F_SETFD, fcntl(sock[i], F_GETFD)|O_NONBLOCK);
77 for (i = 0; i < NUM_CONNS; i++) {
78 int ret, totlen = len[i] + sizeof(len[i]);
79 if (done[i] < sizeof(len[i]) + len[i]) {
81 ret = write(sock[i], (void *)&data + done[i],
85 else if (ret < 0 && errno != EAGAIN)
88 int off = done[i] - totlen;
89 ret = read(sock[i], (void *)&result[i] + off,
90 sizeof(result[i]) - off);
94 + sizeof(result[i])) {
95 assert(result[i] == len[i]);
99 } else if (ret < 0 && errno != EAGAIN)
105 printf("Child did %u\n", count);
109 static int timeout[2];
110 static void sigalarm(int sig)
112 write(timeout[1], "1", 1);
115 static struct io_op *do_timeout(struct io_conn *conn, char *buf)
117 return io_break(conn, NULL);
120 static struct io_op *do_timeout_read(struct io_conn *conn, char *buf)
122 return io_read(buf, 1, io_next(conn, do_timeout, buf));
125 int main(int argc, char *argv[])
128 struct sockaddr_un addr;
129 struct timespec start, end;
130 char buffer[REQUEST_MAX];
134 addr.sun_family = AF_UNIX;
135 sprintf(addr.sun_path, "/tmp/run-different-speed.sock.%u", getpid());
137 if (pipe(wake) != 0 || pipe(timeout) != 0)
138 err(1, "Creating pipes");
140 fd = socket(AF_UNIX, SOCK_STREAM, 0);
142 err(1, "Creating socket");
144 if (bind(fd, (void *)&addr, sizeof(addr)) != 0)
145 err(1, "Binding to %s", addr.sun_path);
147 if (listen(fd, NUM_CONNS) != 0)
148 err(1, "Listening on %s", addr.sun_path);
150 for (i = 0; i < NUM_CHILDREN; i++) {
156 create_clients(&addr, wake[0]);
159 for (j = 0; j < NUM_CONNS; j++) {
160 struct client *client = malloc(sizeof(*client));
161 int ret = accept(fd, NULL, 0);
163 err(1, "Accepting fd");
164 /* For efficiency, we share buffer */
165 client->request_buffer = buffer;
166 io_new_conn(ret, read_header, NULL, client);
170 io_new_conn(timeout[0], do_timeout_read, NULL, &buf);
173 for (i = 0; i < NUM_CHILDREN; i++)
174 write(wake[1], "1", 1);
176 signal(SIGALRM, sigalarm);
183 printf("%u connections complete (%u ns per conn)\n",
185 (int)time_to_nsec(time_divide(time_sub(end, start), completed)));