~ubuntu-branches/ubuntu/trusty/serf/trusty-security

« back to all changes in this revision

Viewing changes to test/test_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Noritada Kobayashi
  • Date: 2008-06-22 11:14:06 UTC
  • mfrom: (1.1.3 upstream) (3.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080622111406-nd0er2lnkdpwqp16
Tags: 0.2.0-1
* New upstream version (Closes: #485025):
  - debian/copyright: Document that CuTest files are licensed under the
    zlib/libpng license.
  - debian/patches/*.diff: Refresh.
* Update Standards-Version to 3.8.0.
  - debian/control: Make binNMU-safe by using ${binary:Version} instead of
    ${Source-Version}.
  - debian/control: Add new Homepage field.
  - debian/copyright: Delete copy of /usr/share/common-licenses/Apache-2.0.
  - debian/README.source: New file explaining quilt.
* Update the debhelper compatibility level to 7.
  - debian/libserf-0-0-dev.install, debian/libserf-0-0.install:
    Do not begin with debian/tmp since it is assumed to be the source path.
* debian/control: Add new Vcs-Git, and Vcs-Browser fields.
* Install test programs as example ones for libserf-0-0-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2002-2007 Justin Erenkrantz and Greg Stein
 
2
 *
 
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
 
6
 *
 
7
 *     http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
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.
 
14
 */
 
15
 
 
16
#include "apr.h"
 
17
#include "apr_pools.h"
 
18
#include <apr_poll.h>
 
19
#include <apr_version.h>
 
20
#include <stdlib.h>
 
21
 
 
22
#include "serf.h"
 
23
 
 
24
#include "test_serf.h"
 
25
 
 
26
/*****************************************************************************/
 
27
/* Server setup functions
 
28
 */
 
29
 
 
30
/* Default implementation of a serf_connection_closed_t callback. */
 
31
static void default_closed_connection(serf_connection_t *conn,
 
32
                                      void *closed_baton,
 
33
                                      apr_status_t why,
 
34
                                      apr_pool_t *pool)
 
35
{
 
36
    if (why) {
 
37
        abort();
 
38
    }
 
39
}
 
40
 
 
41
/* Default implementation of a serf_connection_setup_t callback. */
 
42
static serf_bucket_t* default_conn_setup(apr_socket_t *skt,
 
43
                                         void *setup_baton,
 
44
                                         apr_pool_t *pool)
 
45
{
 
46
    test_baton_t *ctx = setup_baton;
 
47
 
 
48
    return serf_bucket_socket_create(skt, ctx->bkt_alloc);
 
49
}
 
50
 
 
51
static apr_status_t get_server_address(apr_sockaddr_t **address,
 
52
                                       apr_pool_t *pool)
 
53
{
 
54
    return apr_sockaddr_info_get(address,
 
55
                                 "localhost", APR_INET, SERV_PORT, 0,
 
56
                                 pool);
 
57
}
 
58
 
 
59
static void next_action(test_baton_t *tb)
 
60
{
 
61
    tb->cur_action++;
 
62
    tb->action_buf_pos = 0;
 
63
}
 
64
 
 
65
static apr_status_t replay(test_baton_t *tb,
 
66
                           apr_pool_t *pool)
 
67
{
 
68
    apr_status_t status = APR_SUCCESS;
 
69
    test_server_action_t *action;
 
70
 
 
71
    if (tb->cur_action >= tb->action_count) {
 
72
        char buf[128];
 
73
        apr_size_t len = sizeof(buf);
 
74
 
 
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");
 
79
 
 
80
            return APR_EGENERAL;
 
81
        }
 
82
 
 
83
        return status;
 
84
    }
 
85
 
 
86
    if (tb->action_list == NULL)
 
87
    {
 
88
        /* we're not expecting any requests to reach this server! */
 
89
        printf("Received request where none was expected\n");
 
90
 
 
91
        return APR_EGENERAL;
 
92
    }
 
93
 
 
94
    action = &tb->action_list[tb->cur_action];
 
95
 
 
96
    if (action->kind == SERVER_RECV)
 
97
    {
 
98
        apr_size_t msg_len, len;
 
99
        char buf[128];
 
100
 
 
101
        msg_len = strlen(action->text);
 
102
 
 
103
        len = msg_len - tb->action_buf_pos;
 
104
        if (len > sizeof(buf))
 
105
            len = sizeof(buf);
 
106
 
 
107
        status = apr_socket_recv(tb->client_sock, buf, &len);
 
108
        if (status != APR_SUCCESS)
 
109
            return status;
 
110
 
 
111
        if (tb->options & TEST_SERVER_DUMP)
 
112
            fwrite(buf, len, 1, stdout);
 
113
 
 
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);
 
118
            printf(")\n");
 
119
            printf("Actual: (\n");
 
120
            fwrite(buf, len, 1, stdout);
 
121
            printf(")\n");
 
122
 
 
123
            return APR_EGENERAL;
 
124
        }
 
125
 
 
126
        tb->action_buf_pos += len;
 
127
 
 
128
        if (tb->action_buf_pos >= msg_len)
 
129
            next_action(tb);
 
130
    }
 
131
    else if (action->kind == SERVER_SEND) {
 
132
        apr_size_t msg_len;
 
133
        apr_size_t len;
 
134
 
 
135
        msg_len = strlen(action->text);
 
136
        len = msg_len - tb->action_buf_pos;
 
137
 
 
138
        status = apr_socket_send(tb->client_sock,
 
139
                                 action->text + tb->action_buf_pos, &len);
 
140
        if (status != APR_SUCCESS)
 
141
            return status;
 
142
 
 
143
        if (tb->options & TEST_SERVER_DUMP)
 
144
            fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
 
145
 
 
146
        tb->action_buf_pos += len;
 
147
 
 
148
        if (tb->action_buf_pos >= msg_len)
 
149
            next_action(tb);
 
150
    }
 
151
    else if (action->kind == SERVER_KILL_CONNECTION) {
 
152
        apr_socket_close(tb->client_sock);
 
153
        tb->client_sock = NULL;
 
154
        next_action(tb);
 
155
    }
 
156
    else {
 
157
        abort();
 
158
    }
 
159
 
 
160
    return status;
 
161
}
 
162
 
 
163
apr_status_t test_server_run(test_baton_t *tb,
 
164
                             apr_short_interval_time_t duration,
 
165
                             apr_pool_t *pool)
 
166
{
 
167
    apr_status_t status;
 
168
    apr_pollset_t *pollset;
 
169
    apr_int32_t num;
 
170
    const apr_pollfd_t *desc;
 
171
 
 
172
    /* create a new pollset */
 
173
    status = apr_pollset_create(&pollset, 32, pool, 0);
 
174
    if (status != APR_SUCCESS)
 
175
        return status;
 
176
 
 
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,
 
181
                             { NULL }, NULL };
 
182
        pfd.desc.s = tb->client_sock;
 
183
        status = apr_pollset_add(pollset, &pfd);
 
184
        if (status != APR_SUCCESS)
 
185
            goto cleanup;
 
186
    }
 
187
    else {
 
188
        apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN, 0,
 
189
                             { NULL }, NULL };
 
190
        pfd.desc.s = tb->serv_sock;
 
191
        status = apr_pollset_add(pollset, &pfd);
 
192
        if (status != APR_SUCCESS)
 
193
            goto cleanup;
 
194
    }
 
195
 
 
196
    status = apr_pollset_poll(pollset, APR_USEC_PER_SEC >> 1, &num, &desc);
 
197
    if (status != APR_SUCCESS)
 
198
        goto cleanup;
 
199
 
 
200
    while (num--) {
 
201
        if (desc->desc.s == tb->serv_sock) {
 
202
            status = apr_socket_accept(&tb->client_sock, tb->serv_sock,
 
203
                                       tb->pool);
 
204
            if (status != APR_SUCCESS)
 
205
                goto cleanup;
 
206
 
 
207
            apr_socket_opt_set(tb->client_sock, APR_SO_NONBLOCK, 1);
 
208
            apr_socket_timeout_set(tb->client_sock, 0);
 
209
 
 
210
            status = APR_SUCCESS;
 
211
            goto cleanup;
 
212
        }
 
213
 
 
214
        if (desc->desc.s == tb->client_sock) {
 
215
            /* Replay data to socket. */
 
216
            status = replay(tb, pool);
 
217
 
 
218
            if (APR_STATUS_IS_EOF(status)) {
 
219
                apr_socket_close(tb->client_sock);
 
220
                tb->client_sock = NULL;
 
221
            }
 
222
            else if (APR_STATUS_IS_EAGAIN(status)) {
 
223
                status = APR_SUCCESS;
 
224
            }
 
225
            else if (status != APR_SUCCESS) {
 
226
                /* Real error. */
 
227
                goto cleanup;
 
228
            }
 
229
        }
 
230
 
 
231
        desc++;
 
232
    }
 
233
 
 
234
cleanup:
 
235
    apr_pollset_destroy(pollset);
 
236
 
 
237
    return status;
 
238
}
 
239
 
 
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,
 
244
                                   apr_pool_t *pool)
 
245
{
 
246
    apr_status_t status;
 
247
    apr_socket_t *serv_sock;
 
248
 
 
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);
 
252
#else
 
253
    status = apr_socket_create(&serv_sock, APR_INET, SOCK_STREAM, pool);
 
254
#endif
 
255
 
 
256
    if (status != APR_SUCCESS)
 
257
        return status;
 
258
 
 
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);
 
262
 
 
263
    status = apr_socket_bind(serv_sock, tb->serv_addr);
 
264
    if (status != APR_SUCCESS)
 
265
        return status;
 
266
 
 
267
    /* Start replay from first action. */
 
268
    tb->cur_action = 0;
 
269
    tb->action_buf_pos = 0;
 
270
 
 
271
    /* listen for clients */
 
272
    apr_socket_listen(serv_sock, SOMAXCONN);
 
273
    if (status != APR_SUCCESS)
 
274
        return status;
 
275
 
 
276
    tb->serv_sock = serv_sock;
 
277
    tb->client_sock = NULL;
 
278
    return APR_SUCCESS;
 
279
}
 
280
 
 
281
/*****************************************************************************/
 
282
 
 
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,
 
286
                                apr_int32_t options,
 
287
                                const char *host_url,
 
288
                                apr_sockaddr_t *address,
 
289
                                serf_connection_setup_t conn_setup,
 
290
                                apr_pool_t *pool)
 
291
{
 
292
    apr_status_t status;
 
293
    test_baton_t *tb;
 
294
 
 
295
    tb = apr_palloc(pool, sizeof(*tb));
 
296
    *tb_p = tb;
 
297
 
 
298
    if (address) {
 
299
        tb->serv_addr = address;
 
300
    }
 
301
    else {
 
302
        status = get_server_address(&tb->serv_addr, pool);
 
303
        if (status != APR_SUCCESS)
 
304
          return status;
 
305
    }
 
306
 
 
307
    tb->pool = pool;
 
308
    tb->options = options;
 
309
    tb->context = serf_context_create(pool);
 
310
    tb->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
 
311
    if (host_url) {
 
312
        apr_uri_t url;
 
313
        status = apr_uri_parse(pool, host_url, &url);
 
314
        if (status != APR_SUCCESS)
 
315
            return status;
 
316
 
 
317
        status = serf_connection_create2(&tb->connection, tb->context,
 
318
                                         url,
 
319
                                         conn_setup ? conn_setup : 
 
320
                                             default_conn_setup,
 
321
                                         tb,
 
322
                                         default_closed_connection,
 
323
                                         tb,
 
324
                                         pool);
 
325
        if (status != APR_SUCCESS)
 
326
          return status;
 
327
    } else {
 
328
        tb->connection = serf_connection_create(tb->context,
 
329
                                                tb->serv_addr,
 
330
                                                conn_setup ? conn_setup : 
 
331
                                                    default_conn_setup,
 
332
                                                tb,
 
333
                                                default_closed_connection,
 
334
                                                tb,
 
335
                                                pool);
 
336
    }
 
337
    tb->action_list = action_list;
 
338
    tb->action_count = action_count;
 
339
 
 
340
    /* Prepare a server. */
 
341
    status = prepare_server(tb, pool);
 
342
    if (status != APR_SUCCESS)
 
343
      return status;
 
344
 
 
345
    return APR_SUCCESS;
 
346
}
 
347
 
 
348
apr_status_t test_server_destroy(test_baton_t *tb, apr_pool_t *pool)
 
349
{
 
350
    serf_connection_close(tb->connection);
 
351
 
 
352
    apr_socket_close(tb->serv_sock);
 
353
 
 
354
    if (tb->client_sock) {
 
355
        apr_socket_close(tb->client_sock);
 
356
    }
 
357
 
 
358
    return APR_SUCCESS;
 
359
}