1
/* Copyright 2002-2007 Justin Erenkrantz and Greg Stein
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
* See the License for the specific language governing permissions and
13
* limitations under the License.
17
#include "apr_pools.h"
19
#include <apr_version.h>
24
#include "test_serf.h"
26
/*****************************************************************************/
27
/* Server setup functions
30
/* Default implementation of a serf_connection_closed_t callback. */
31
static void default_closed_connection(serf_connection_t *conn,
41
/* Default implementation of a serf_connection_setup_t callback. */
42
static serf_bucket_t* default_conn_setup(apr_socket_t *skt,
46
test_baton_t *ctx = setup_baton;
48
return serf_bucket_socket_create(skt, ctx->bkt_alloc);
51
static apr_status_t get_server_address(apr_sockaddr_t **address,
54
return apr_sockaddr_info_get(address,
55
"localhost", APR_INET, SERV_PORT, 0,
59
static void next_action(test_baton_t *tb)
62
tb->action_buf_pos = 0;
65
static apr_status_t replay(test_baton_t *tb,
68
apr_status_t status = APR_SUCCESS;
69
test_server_action_t *action;
71
if (tb->cur_action >= tb->action_count) {
73
apr_size_t len = sizeof(buf);
75
status = apr_socket_recv(tb->client_sock, buf, &len);
76
if (! APR_STATUS_IS_EAGAIN(status)) {
77
/* we're out of actions! */
78
printf("Received more requests than expected\n");
86
if (tb->action_list == NULL)
88
/* we're not expecting any requests to reach this server! */
89
printf("Received request where none was expected\n");
94
action = &tb->action_list[tb->cur_action];
96
if (action->kind == SERVER_RECV)
98
apr_size_t msg_len, len;
101
msg_len = strlen(action->text);
103
len = msg_len - tb->action_buf_pos;
104
if (len > sizeof(buf))
107
status = apr_socket_recv(tb->client_sock, buf, &len);
108
if (status != APR_SUCCESS)
111
if (tb->options & TEST_SERVER_DUMP)
112
fwrite(buf, len, 1, stdout);
114
if (strncmp(buf, action->text + tb->action_buf_pos, len) != 0) {
115
/* ## TODO: Better diagnostics. */
116
printf("Expected: (\n");
117
fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
119
printf("Actual: (\n");
120
fwrite(buf, len, 1, stdout);
126
tb->action_buf_pos += len;
128
if (tb->action_buf_pos >= msg_len)
131
else if (action->kind == SERVER_SEND) {
135
msg_len = strlen(action->text);
136
len = msg_len - tb->action_buf_pos;
138
status = apr_socket_send(tb->client_sock,
139
action->text + tb->action_buf_pos, &len);
140
if (status != APR_SUCCESS)
143
if (tb->options & TEST_SERVER_DUMP)
144
fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
146
tb->action_buf_pos += len;
148
if (tb->action_buf_pos >= msg_len)
151
else if (action->kind == SERVER_KILL_CONNECTION) {
152
apr_socket_close(tb->client_sock);
153
tb->client_sock = NULL;
163
apr_status_t test_server_run(test_baton_t *tb,
164
apr_short_interval_time_t duration,
168
apr_pollset_t *pollset;
170
const apr_pollfd_t *desc;
172
/* create a new pollset */
173
status = apr_pollset_create(&pollset, 32, pool, 0);
174
if (status != APR_SUCCESS)
177
/* Don't accept new connection while processing client connection. At
178
least for present time.*/
179
if (tb->client_sock) {
180
apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN | APR_POLLOUT, 0,
182
pfd.desc.s = tb->client_sock;
183
status = apr_pollset_add(pollset, &pfd);
184
if (status != APR_SUCCESS)
188
apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN, 0,
190
pfd.desc.s = tb->serv_sock;
191
status = apr_pollset_add(pollset, &pfd);
192
if (status != APR_SUCCESS)
196
status = apr_pollset_poll(pollset, APR_USEC_PER_SEC >> 1, &num, &desc);
197
if (status != APR_SUCCESS)
201
if (desc->desc.s == tb->serv_sock) {
202
status = apr_socket_accept(&tb->client_sock, tb->serv_sock,
204
if (status != APR_SUCCESS)
207
apr_socket_opt_set(tb->client_sock, APR_SO_NONBLOCK, 1);
208
apr_socket_timeout_set(tb->client_sock, 0);
210
status = APR_SUCCESS;
214
if (desc->desc.s == tb->client_sock) {
215
/* Replay data to socket. */
216
status = replay(tb, pool);
218
if (APR_STATUS_IS_EOF(status)) {
219
apr_socket_close(tb->client_sock);
220
tb->client_sock = NULL;
222
else if (APR_STATUS_IS_EAGAIN(status)) {
223
status = APR_SUCCESS;
225
else if (status != APR_SUCCESS) {
235
apr_pollset_destroy(pollset);
240
/* Start a TCP server on port SERV_PORT in thread THREAD. srv_replay is a array
241
of action to replay when connection started. replay_count is count of
242
actions in srv_replay. */
243
static apr_status_t prepare_server(test_baton_t *tb,
247
apr_socket_t *serv_sock;
249
/* create server socket */
250
#if APR_VERSION_AT_LEAST(1, 0, 0)
251
status = apr_socket_create(&serv_sock, APR_INET, SOCK_STREAM, 0, pool);
253
status = apr_socket_create(&serv_sock, APR_INET, SOCK_STREAM, pool);
256
if (status != APR_SUCCESS)
259
apr_socket_opt_set(serv_sock, APR_SO_NONBLOCK, 1);
260
apr_socket_timeout_set(serv_sock, 0);
261
apr_socket_opt_set(serv_sock, APR_SO_REUSEADDR, 1);
263
status = apr_socket_bind(serv_sock, tb->serv_addr);
264
if (status != APR_SUCCESS)
267
/* Start replay from first action. */
269
tb->action_buf_pos = 0;
271
/* listen for clients */
272
apr_socket_listen(serv_sock, SOMAXCONN);
273
if (status != APR_SUCCESS)
276
tb->serv_sock = serv_sock;
277
tb->client_sock = NULL;
281
/*****************************************************************************/
283
apr_status_t test_server_create(test_baton_t **tb_p,
284
test_server_action_t *action_list,
285
apr_size_t action_count,
287
const char *host_url,
288
apr_sockaddr_t *address,
289
serf_connection_setup_t conn_setup,
295
tb = apr_palloc(pool, sizeof(*tb));
299
tb->serv_addr = address;
302
status = get_server_address(&tb->serv_addr, pool);
303
if (status != APR_SUCCESS)
308
tb->options = options;
309
tb->context = serf_context_create(pool);
310
tb->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
313
status = apr_uri_parse(pool, host_url, &url);
314
if (status != APR_SUCCESS)
317
status = serf_connection_create2(&tb->connection, tb->context,
319
conn_setup ? conn_setup :
322
default_closed_connection,
325
if (status != APR_SUCCESS)
328
tb->connection = serf_connection_create(tb->context,
330
conn_setup ? conn_setup :
333
default_closed_connection,
337
tb->action_list = action_list;
338
tb->action_count = action_count;
340
/* Prepare a server. */
341
status = prepare_server(tb, pool);
342
if (status != APR_SUCCESS)
348
apr_status_t test_server_destroy(test_baton_t *tb, apr_pool_t *pool)
350
serf_connection_close(tb->connection);
352
apr_socket_close(tb->serv_sock);
354
if (tb->client_sock) {
355
apr_socket_close(tb->client_sock);