Annotation of embedaddon/libevent/test/regress_rpc.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. The name of the author may not be used to endorse or promote products
        !            14:  *    derived from this software without specific prior written permission.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            26:  */
        !            27: 
        !            28: #ifdef WIN32
        !            29: #include <winsock2.h>
        !            30: #include <windows.h>
        !            31: #endif
        !            32: 
        !            33: #ifdef HAVE_CONFIG_H
        !            34: #include "config.h"
        !            35: #endif
        !            36: 
        !            37: #include <sys/types.h>
        !            38: #include <sys/stat.h>
        !            39: #ifdef HAVE_SYS_TIME_H
        !            40: #include <sys/time.h>
        !            41: #endif
        !            42: #include <sys/queue.h>
        !            43: #ifndef WIN32
        !            44: #include <sys/socket.h>
        !            45: #include <signal.h>
        !            46: #include <unistd.h>
        !            47: #include <netdb.h>
        !            48: #endif
        !            49: #include <fcntl.h>
        !            50: #include <stdlib.h>
        !            51: #include <stdio.h>
        !            52: #include <string.h>
        !            53: #include <errno.h>
        !            54: #include <assert.h>
        !            55: 
        !            56: #include "event.h"
        !            57: #include "evhttp.h"
        !            58: #include "log.h"
        !            59: #include "evrpc.h"
        !            60: 
        !            61: #include "regress.gen.h"
        !            62: 
        !            63: void rpc_suite(void);
        !            64: 
        !            65: extern int test_ok;
        !            66: 
        !            67: static struct evhttp *
        !            68: http_setup(short *pport)
        !            69: {
        !            70:        int i;
        !            71:        struct evhttp *myhttp;
        !            72:        short port = -1;
        !            73: 
        !            74:        /* Try a few different ports */
        !            75:        for (i = 0; i < 50; ++i) {
        !            76:                myhttp = evhttp_start("127.0.0.1", 8080 + i);
        !            77:                if (myhttp != NULL) {
        !            78:                        port = 8080 + i;
        !            79:                        break;
        !            80:                }
        !            81:        }
        !            82: 
        !            83:        if (port == -1)
        !            84:                event_errx(1, "Could not start web server");
        !            85: 
        !            86:        *pport = port;
        !            87:        return (myhttp);
        !            88: }
        !            89: 
        !            90: EVRPC_HEADER(Message, msg, kill);
        !            91: EVRPC_HEADER(NeverReply, msg, kill);
        !            92: 
        !            93: EVRPC_GENERATE(Message, msg, kill);
        !            94: EVRPC_GENERATE(NeverReply, msg, kill);
        !            95: 
        !            96: static int need_input_hook = 0;
        !            97: static int need_output_hook = 0;
        !            98: 
        !            99: static void
        !           100: MessageCb(EVRPC_STRUCT(Message)* rpc, void *arg)
        !           101: {
        !           102:        struct kill* kill_reply = rpc->reply;
        !           103: 
        !           104:        if (need_input_hook) {
        !           105:                struct evhttp_request* req = EVRPC_REQUEST_HTTP(rpc);
        !           106:                const char *header = evhttp_find_header(
        !           107:                        req->input_headers, "X-Hook");
        !           108:                assert(strcmp(header, "input") == 0);
        !           109:        }
        !           110: 
        !           111:        /* we just want to fill in some non-sense */
        !           112:        EVTAG_ASSIGN(kill_reply, weapon, "dagger");
        !           113:        EVTAG_ASSIGN(kill_reply, action, "wave around like an idiot");
        !           114: 
        !           115:        /* no reply to the RPC */
        !           116:        EVRPC_REQUEST_DONE(rpc);
        !           117: }
        !           118: 
        !           119: static EVRPC_STRUCT(NeverReply) *saved_rpc;
        !           120: 
        !           121: static void
        !           122: NeverReplyCb(EVRPC_STRUCT(NeverReply)* rpc, void *arg)
        !           123: {
        !           124:        test_ok += 1;
        !           125:        saved_rpc = rpc;
        !           126: }
        !           127: 
        !           128: static void
        !           129: rpc_setup(struct evhttp **phttp, short *pport, struct evrpc_base **pbase)
        !           130: {
        !           131:        short port;
        !           132:        struct evhttp *http = NULL;
        !           133:        struct evrpc_base *base = NULL;
        !           134: 
        !           135:        http = http_setup(&port);
        !           136:        base = evrpc_init(http);
        !           137:        
        !           138:        EVRPC_REGISTER(base, Message, msg, kill, MessageCb, NULL);
        !           139:        EVRPC_REGISTER(base, NeverReply, msg, kill, NeverReplyCb, NULL);
        !           140: 
        !           141:        *phttp = http;
        !           142:        *pport = port;
        !           143:        *pbase = base;
        !           144: 
        !           145:        need_input_hook = 0;
        !           146:        need_output_hook = 0;
        !           147: }
        !           148: 
        !           149: static void
        !           150: rpc_teardown(struct evrpc_base *base)
        !           151: {
        !           152:        assert(EVRPC_UNREGISTER(base, Message) == 0);
        !           153:        assert(EVRPC_UNREGISTER(base, NeverReply) == 0);
        !           154: 
        !           155:        evrpc_free(base);
        !           156: }
        !           157: 
        !           158: static void
        !           159: rpc_postrequest_failure(struct evhttp_request *req, void *arg)
        !           160: {
        !           161:        if (req->response_code != HTTP_SERVUNAVAIL) {
        !           162:        
        !           163:                fprintf(stderr, "FAILED (response code)\n");
        !           164:                exit(1);
        !           165:        }
        !           166: 
        !           167:        test_ok = 1;
        !           168:        event_loopexit(NULL);
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * Test a malformed payload submitted as an RPC
        !           173:  */
        !           174: 
        !           175: static void
        !           176: rpc_basic_test(void)
        !           177: {
        !           178:        short port;
        !           179:        struct evhttp *http = NULL;
        !           180:        struct evrpc_base *base = NULL;
        !           181:        struct evhttp_connection *evcon = NULL;
        !           182:        struct evhttp_request *req = NULL;
        !           183: 
        !           184:        fprintf(stdout, "Testing Basic RPC Support: ");
        !           185: 
        !           186:        rpc_setup(&http, &port, &base);
        !           187: 
        !           188:        evcon = evhttp_connection_new("127.0.0.1", port);
        !           189:        if (evcon == NULL) {
        !           190:                fprintf(stdout, "FAILED\n");
        !           191:                exit(1);
        !           192:        }
        !           193: 
        !           194:        /*
        !           195:         * At this point, we want to schedule an HTTP POST request
        !           196:         * server using our make request method.
        !           197:         */
        !           198: 
        !           199:        req = evhttp_request_new(rpc_postrequest_failure, NULL);
        !           200:        if (req == NULL) {
        !           201:                fprintf(stdout, "FAILED\n");
        !           202:                exit(1);
        !           203:        }
        !           204: 
        !           205:        /* Add the information that we care about */
        !           206:        evhttp_add_header(req->output_headers, "Host", "somehost");
        !           207:        evbuffer_add_printf(req->output_buffer, "Some Nonsense");
        !           208:        
        !           209:        if (evhttp_make_request(evcon, req,
        !           210:                EVHTTP_REQ_POST,
        !           211:                "/.rpc.Message") == -1) {
        !           212:                fprintf(stdout, "FAILED\n");
        !           213:                exit(1);
        !           214:        }
        !           215: 
        !           216:        test_ok = 0;
        !           217: 
        !           218:        event_dispatch();
        !           219: 
        !           220:        evhttp_connection_free(evcon);
        !           221: 
        !           222:        rpc_teardown(base);
        !           223:        
        !           224:        if (test_ok != 1) {
        !           225:                fprintf(stdout, "FAILED\n");
        !           226:                exit(1);
        !           227:        }
        !           228: 
        !           229:        fprintf(stdout, "OK\n");
        !           230: 
        !           231:        evhttp_free(http);
        !           232: }
        !           233: 
        !           234: static void
        !           235: rpc_postrequest_done(struct evhttp_request *req, void *arg)
        !           236: {
        !           237:        struct kill* kill_reply = NULL;
        !           238: 
        !           239:        if (req->response_code != HTTP_OK) {
        !           240:        
        !           241:                fprintf(stderr, "FAILED (response code)\n");
        !           242:                exit(1);
        !           243:        }
        !           244: 
        !           245:        kill_reply = kill_new();
        !           246: 
        !           247:        if ((kill_unmarshal(kill_reply, req->input_buffer)) == -1) {
        !           248:                fprintf(stderr, "FAILED (unmarshal)\n");
        !           249:                exit(1);
        !           250:        }
        !           251:        
        !           252:        kill_free(kill_reply);
        !           253: 
        !           254:        test_ok = 1;
        !           255:        event_loopexit(NULL);
        !           256: }
        !           257: 
        !           258: static void
        !           259: rpc_basic_message(void)
        !           260: {
        !           261:        short port;
        !           262:        struct evhttp *http = NULL;
        !           263:        struct evrpc_base *base = NULL;
        !           264:        struct evhttp_connection *evcon = NULL;
        !           265:        struct evhttp_request *req = NULL;
        !           266:        struct msg *msg;
        !           267: 
        !           268:        fprintf(stdout, "Testing Good RPC Post: ");
        !           269: 
        !           270:        rpc_setup(&http, &port, &base);
        !           271: 
        !           272:        evcon = evhttp_connection_new("127.0.0.1", port);
        !           273:        if (evcon == NULL) {
        !           274:                fprintf(stdout, "FAILED\n");
        !           275:                exit(1);
        !           276:        }
        !           277: 
        !           278:        /*
        !           279:         * At this point, we want to schedule an HTTP POST request
        !           280:         * server using our make request method.
        !           281:         */
        !           282: 
        !           283:        req = evhttp_request_new(rpc_postrequest_done, NULL);
        !           284:        if (req == NULL) {
        !           285:                fprintf(stdout, "FAILED\n");
        !           286:                exit(1);
        !           287:        }
        !           288: 
        !           289:        /* Add the information that we care about */
        !           290:        evhttp_add_header(req->output_headers, "Host", "somehost");
        !           291: 
        !           292:        /* set up the basic message */
        !           293:        msg = msg_new();
        !           294:        EVTAG_ASSIGN(msg, from_name, "niels");
        !           295:        EVTAG_ASSIGN(msg, to_name, "tester");
        !           296:        msg_marshal(req->output_buffer, msg);
        !           297:        msg_free(msg);
        !           298: 
        !           299:        if (evhttp_make_request(evcon, req,
        !           300:                EVHTTP_REQ_POST,
        !           301:                "/.rpc.Message") == -1) {
        !           302:                fprintf(stdout, "FAILED\n");
        !           303:                exit(1);
        !           304:        }
        !           305: 
        !           306:        test_ok = 0;
        !           307: 
        !           308:        event_dispatch();
        !           309: 
        !           310:        evhttp_connection_free(evcon);
        !           311:        
        !           312:        rpc_teardown(base);
        !           313:        
        !           314:        if (test_ok != 1) {
        !           315:                fprintf(stdout, "FAILED\n");
        !           316:                exit(1);
        !           317:        }
        !           318: 
        !           319:        fprintf(stdout, "OK\n");
        !           320: 
        !           321:        evhttp_free(http);
        !           322: }
        !           323: 
        !           324: static struct evrpc_pool *
        !           325: rpc_pool_with_connection(short port)
        !           326: {
        !           327:        struct evhttp_connection *evcon;
        !           328:        struct evrpc_pool *pool;
        !           329: 
        !           330:        pool = evrpc_pool_new(NULL);
        !           331:        assert(pool != NULL);
        !           332: 
        !           333:        evcon = evhttp_connection_new("127.0.0.1", port);
        !           334:        assert(evcon != NULL);
        !           335: 
        !           336:        evrpc_pool_add_connection(pool, evcon);
        !           337:        
        !           338:        return (pool);
        !           339: }
        !           340: 
        !           341: static void
        !           342: GotKillCb(struct evrpc_status *status,
        !           343:     struct msg *msg, struct kill *kill, void *arg)
        !           344: {
        !           345:        char *weapon;
        !           346:        char *action;
        !           347: 
        !           348:        if (need_output_hook) {
        !           349:                struct evhttp_request *req = status->http_req;
        !           350:                const char *header = evhttp_find_header(
        !           351:                        req->input_headers, "X-Pool-Hook");
        !           352:                assert(strcmp(header, "ran") == 0);
        !           353:        }
        !           354: 
        !           355:        if (status->error != EVRPC_STATUS_ERR_NONE)
        !           356:                goto done;
        !           357: 
        !           358:        if (EVTAG_GET(kill, weapon, &weapon) == -1) {
        !           359:                fprintf(stderr, "get weapon\n");
        !           360:                goto done;
        !           361:        }
        !           362:        if (EVTAG_GET(kill, action, &action) == -1) {
        !           363:                fprintf(stderr, "get action\n");
        !           364:                goto done;
        !           365:        }
        !           366: 
        !           367:        if (strcmp(weapon, "dagger"))
        !           368:                goto done;
        !           369: 
        !           370:        if (strcmp(action, "wave around like an idiot"))
        !           371:                goto done;
        !           372: 
        !           373:        test_ok += 1;
        !           374: 
        !           375: done:
        !           376:        event_loopexit(NULL);
        !           377: }
        !           378: 
        !           379: static void
        !           380: GotKillCbTwo(struct evrpc_status *status,
        !           381:     struct msg *msg, struct kill *kill, void *arg)
        !           382: {
        !           383:        char *weapon;
        !           384:        char *action;
        !           385: 
        !           386:        if (status->error != EVRPC_STATUS_ERR_NONE)
        !           387:                goto done;
        !           388: 
        !           389:        if (EVTAG_GET(kill, weapon, &weapon) == -1) {
        !           390:                fprintf(stderr, "get weapon\n");
        !           391:                goto done;
        !           392:        }
        !           393:        if (EVTAG_GET(kill, action, &action) == -1) {
        !           394:                fprintf(stderr, "get action\n");
        !           395:                goto done;
        !           396:        }
        !           397: 
        !           398:        if (strcmp(weapon, "dagger"))
        !           399:                goto done;
        !           400: 
        !           401:        if (strcmp(action, "wave around like an idiot"))
        !           402:                goto done;
        !           403: 
        !           404:        test_ok += 1;
        !           405: 
        !           406: done:
        !           407:        if (test_ok == 2)
        !           408:                event_loopexit(NULL);
        !           409: }
        !           410: 
        !           411: static int
        !           412: rpc_hook_add_header(struct evhttp_request *req,
        !           413:     struct evbuffer *evbuf, void *arg)
        !           414: {
        !           415:        const char *hook_type = arg;
        !           416:        if (strcmp("input", hook_type) == 0)
        !           417:                evhttp_add_header(req->input_headers, "X-Hook", hook_type);
        !           418:        else 
        !           419:                evhttp_add_header(req->output_headers, "X-Hook", hook_type);
        !           420:        return (0);
        !           421: }
        !           422: 
        !           423: static int
        !           424: rpc_hook_remove_header(struct evhttp_request *req,
        !           425:     struct evbuffer *evbuf, void *arg)
        !           426: {
        !           427:        const char *header = evhttp_find_header(req->input_headers, "X-Hook");
        !           428:        assert(header != NULL);
        !           429:        assert(strcmp(header, arg) == 0);
        !           430:        evhttp_remove_header(req->input_headers, "X-Hook");
        !           431:        evhttp_add_header(req->input_headers, "X-Pool-Hook", "ran");
        !           432: 
        !           433:        return (0);
        !           434: }
        !           435: 
        !           436: static void
        !           437: rpc_basic_client(void)
        !           438: {
        !           439:        short port;
        !           440:        struct evhttp *http = NULL;
        !           441:        struct evrpc_base *base = NULL;
        !           442:        struct evrpc_pool *pool = NULL;
        !           443:        struct msg *msg;
        !           444:        struct kill *kill;
        !           445: 
        !           446:        fprintf(stdout, "Testing RPC Client: ");
        !           447: 
        !           448:        rpc_setup(&http, &port, &base);
        !           449: 
        !           450:        need_input_hook = 1;
        !           451:        need_output_hook = 1;
        !           452: 
        !           453:        assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_add_header, (void*)"input")
        !           454:            != NULL);
        !           455:        assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_add_header, (void*)"output")
        !           456:            != NULL);
        !           457: 
        !           458:        pool = rpc_pool_with_connection(port);
        !           459: 
        !           460:        assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_remove_header, (void*)"output"));
        !           461: 
        !           462:        /* set up the basic message */
        !           463:        msg = msg_new();
        !           464:        EVTAG_ASSIGN(msg, from_name, "niels");
        !           465:        EVTAG_ASSIGN(msg, to_name, "tester");
        !           466: 
        !           467:        kill = kill_new();
        !           468: 
        !           469:        EVRPC_MAKE_REQUEST(Message, pool, msg, kill,  GotKillCb, NULL);
        !           470: 
        !           471:        test_ok = 0;
        !           472: 
        !           473:        event_dispatch();
        !           474:        
        !           475:        if (test_ok != 1) {
        !           476:                fprintf(stdout, "FAILED (1)\n");
        !           477:                exit(1);
        !           478:        }
        !           479: 
        !           480:        /* we do it twice to make sure that reuse works correctly */
        !           481:        kill_clear(kill);
        !           482: 
        !           483:        EVRPC_MAKE_REQUEST(Message, pool, msg, kill,  GotKillCb, NULL);
        !           484: 
        !           485:        event_dispatch();
        !           486:        
        !           487:        rpc_teardown(base);
        !           488:        
        !           489:        if (test_ok != 2) {
        !           490:                fprintf(stdout, "FAILED (2)\n");
        !           491:                exit(1);
        !           492:        }
        !           493: 
        !           494:        fprintf(stdout, "OK\n");
        !           495: 
        !           496:        msg_free(msg);
        !           497:        kill_free(kill);
        !           498: 
        !           499:        evrpc_pool_free(pool);
        !           500:        evhttp_free(http);
        !           501: }
        !           502: 
        !           503: /* 
        !           504:  * We are testing that the second requests gets send over the same
        !           505:  * connection after the first RPCs completes.
        !           506:  */
        !           507: static void
        !           508: rpc_basic_queued_client(void)
        !           509: {
        !           510:        short port;
        !           511:        struct evhttp *http = NULL;
        !           512:        struct evrpc_base *base = NULL;
        !           513:        struct evrpc_pool *pool = NULL;
        !           514:        struct msg *msg;
        !           515:        struct kill *kill_one, *kill_two;
        !           516: 
        !           517:        fprintf(stdout, "Testing RPC (Queued) Client: ");
        !           518: 
        !           519:        rpc_setup(&http, &port, &base);
        !           520: 
        !           521:        pool = rpc_pool_with_connection(port);
        !           522: 
        !           523:        /* set up the basic message */
        !           524:        msg = msg_new();
        !           525:        EVTAG_ASSIGN(msg, from_name, "niels");
        !           526:        EVTAG_ASSIGN(msg, to_name, "tester");
        !           527: 
        !           528:        kill_one = kill_new();
        !           529:        kill_two = kill_new();
        !           530: 
        !           531:        EVRPC_MAKE_REQUEST(Message, pool, msg, kill_one,  GotKillCbTwo, NULL);
        !           532:        EVRPC_MAKE_REQUEST(Message, pool, msg, kill_two,  GotKillCb, NULL);
        !           533: 
        !           534:        test_ok = 0;
        !           535: 
        !           536:        event_dispatch();
        !           537:        
        !           538:        rpc_teardown(base);
        !           539:        
        !           540:        if (test_ok != 2) {
        !           541:                fprintf(stdout, "FAILED (1)\n");
        !           542:                exit(1);
        !           543:        }
        !           544: 
        !           545:        fprintf(stdout, "OK\n");
        !           546: 
        !           547:        msg_free(msg);
        !           548:        kill_free(kill_one);
        !           549:        kill_free(kill_two);
        !           550: 
        !           551:        evrpc_pool_free(pool);
        !           552:        evhttp_free(http);
        !           553: }
        !           554: 
        !           555: static void
        !           556: GotErrorCb(struct evrpc_status *status,
        !           557:     struct msg *msg, struct kill *kill, void *arg)
        !           558: {
        !           559:        if (status->error != EVRPC_STATUS_ERR_TIMEOUT)
        !           560:                goto done;
        !           561: 
        !           562:        /* should never be complete but just to check */
        !           563:        if (kill_complete(kill) == 0)
        !           564:                goto done;
        !           565: 
        !           566:        test_ok += 1;
        !           567: 
        !           568: done:
        !           569:        event_loopexit(NULL);
        !           570: }
        !           571: 
        !           572: static void
        !           573: rpc_client_timeout(void)
        !           574: {
        !           575:        short port;
        !           576:        struct evhttp *http = NULL;
        !           577:        struct evrpc_base *base = NULL;
        !           578:        struct evrpc_pool *pool = NULL;
        !           579:        struct msg *msg;
        !           580:        struct kill *kill;
        !           581: 
        !           582:        fprintf(stdout, "Testing RPC Client Timeout: ");
        !           583: 
        !           584:        rpc_setup(&http, &port, &base);
        !           585: 
        !           586:        pool = rpc_pool_with_connection(port);
        !           587: 
        !           588:        /* set the timeout to 5 seconds */
        !           589:        evrpc_pool_set_timeout(pool, 5);
        !           590: 
        !           591:        /* set up the basic message */
        !           592:        msg = msg_new();
        !           593:        EVTAG_ASSIGN(msg, from_name, "niels");
        !           594:        EVTAG_ASSIGN(msg, to_name, "tester");
        !           595: 
        !           596:        kill = kill_new();
        !           597: 
        !           598:        EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL);
        !           599: 
        !           600:        test_ok = 0;
        !           601: 
        !           602:        event_dispatch();
        !           603:        
        !           604:        /* free the saved RPC structure up */
        !           605:        EVRPC_REQUEST_DONE(saved_rpc);
        !           606: 
        !           607:        rpc_teardown(base);
        !           608:        
        !           609:        if (test_ok != 2) {
        !           610:                fprintf(stdout, "FAILED (1)\n");
        !           611:                exit(1);
        !           612:        }
        !           613: 
        !           614:        fprintf(stdout, "OK\n");
        !           615: 
        !           616:        msg_free(msg);
        !           617:        kill_free(kill);
        !           618: 
        !           619:        evrpc_pool_free(pool);
        !           620:        evhttp_free(http);
        !           621: }
        !           622: 
        !           623: void
        !           624: rpc_suite(void)
        !           625: {
        !           626:        rpc_basic_test();
        !           627:        rpc_basic_message();
        !           628:        rpc_basic_client();
        !           629:        rpc_basic_queued_client();
        !           630:        rpc_client_timeout();
        !           631: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>