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>
16 #define REQUEST_SIZE 1024
17 #define REPLY_SIZE 10240
18 #define NUM_CONNS 500 /* per child */
19 #define NUM_CHILDREN 2
21 static unsigned int completed;
24 char request_buffer[REQUEST_SIZE];
25 char reply_buffer[REPLY_SIZE];
28 static struct io_plan write_reply(struct io_conn *conn, struct client *client);
29 static struct io_plan read_request(struct io_conn *conn, struct client *client)
31 return io_read(client->request_buffer, REQUEST_SIZE,
35 /* once we're done, loop again. */
36 static struct io_plan write_complete(struct io_conn *conn, struct client *client)
39 return read_request(conn, client);
42 static struct io_plan write_reply(struct io_conn *conn, struct client *client)
44 return io_write(client->reply_buffer, REPLY_SIZE,
45 write_complete, client);
48 /* This runs in the child. */
49 static void create_clients(struct sockaddr_un *addr, int waitfd)
52 int i, sock[NUM_CONNS], speed[NUM_CONNS], done[NUM_CONNS], count = 0;
54 for (i = 0; i < NUM_CONNS; i++) {
56 speed[i] = (1 << (random() % 10));
57 sock[i] = socket(AF_UNIX, SOCK_STREAM, 0);
59 err(1, "creating socket");
60 if (connect(sock[i], (void *)addr, sizeof(*addr)) != 0)
61 err(1, "connecting socket");
62 /* Make nonblocking. */
63 fcntl(sock[i], F_SETFD, fcntl(sock[i], F_GETFD)|O_NONBLOCK);
70 for (i = 0; i < NUM_CONNS; i++) {
71 int ret, bytes = speed[i];
72 if (done[i] < REQUEST_SIZE) {
73 if (REQUEST_SIZE - done[i] < bytes)
74 bytes = REQUEST_SIZE - done[i];
75 ret = write(sock[i], data.request_buffer,
79 else if (ret < 0 && errno != EAGAIN)
82 if (REQUEST_SIZE + REPLY_SIZE - done[i] < bytes)
83 bytes = REQUEST_SIZE + REPLY_SIZE
85 ret = read(sock[i], data.reply_buffer,
89 if (done[i] == REQUEST_SIZE + REPLY_SIZE) {
93 } else if (ret < 0 && errno != EAGAIN)
99 printf("Child did %u\n", count);
103 static int timeout[2];
104 static void sigalarm(int sig)
106 write(timeout[1], "1", 1);
109 static struct io_plan do_timeout(struct io_conn *conn, char *buf)
111 return io_break(buf, io_idle());
114 int main(int argc, char *argv[])
116 struct client client;
118 struct sockaddr_un addr;
119 struct timespec start, end;
123 addr.sun_family = AF_UNIX;
124 sprintf(addr.sun_path, "/tmp/run-different-speed.sock.%u", getpid());
126 if (pipe(wake) != 0 || pipe(timeout) != 0)
127 err(1, "Creating pipes");
129 fd = socket(AF_UNIX, SOCK_STREAM, 0);
131 err(1, "Creating socket");
133 if (bind(fd, (void *)&addr, sizeof(addr)) != 0)
134 err(1, "Binding to %s", addr.sun_path);
136 if (listen(fd, NUM_CONNS) != 0)
137 err(1, "Listening on %s", addr.sun_path);
139 for (i = 0; i < NUM_CHILDREN; i++) {
145 create_clients(&addr, wake[0]);
148 for (j = 0; j < NUM_CONNS; j++) {
149 int ret = accept(fd, NULL, 0);
151 err(1, "Accepting fd");
152 /* For efficiency, we share client structure */
154 io_read(client.request_buffer, REQUEST_SIZE,
155 write_reply, &client));
159 io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf));
162 for (i = 0; i < NUM_CHILDREN; i++)
163 write(wake[1], "1", 1);
165 signal(SIGALRM, sigalarm);
172 printf("%u connections complete (%u ns per conn)\n",
174 (int)time_to_nsec(time_divide(time_sub(end, start), completed)));