root/opal/mca/event/libevent2022/libevent/test/regress_listener.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acceptcb
  2. regress_pick_a_port
  3. errorcb
  4. regress_listener_error

   1 /*
   2  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  * 3. The name of the author may not be used to endorse or promote products
  13  *    derived from this software without specific prior written permission.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  */
  26 
  27 #ifdef WIN32
  28 #include <winsock2.h>
  29 #include <windows.h>
  30 #endif
  31 
  32 #include <sys/types.h>
  33 
  34 #ifndef WIN32
  35 #include <sys/socket.h>
  36 #include <netinet/in.h>
  37 # ifdef _XOPEN_SOURCE_EXTENDED
  38 #  include <arpa/inet.h>
  39 # endif
  40 #include <unistd.h>
  41 #endif
  42 
  43 #include <string.h>
  44 
  45 #include "event2/listener.h"
  46 #include "event2/event.h"
  47 #include "event2/util.h"
  48 
  49 #include "regress.h"
  50 #include "tinytest.h"
  51 #include "tinytest_macros.h"
  52 #include "util-internal.h"
  53 
  54 static void
  55 acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
  56     struct sockaddr *addr, int socklen, void *arg)
  57 {
  58         int *ptr = arg;
  59         --*ptr;
  60         TT_BLATHER(("Got one for %p", ptr));
  61         evutil_closesocket(fd);
  62 
  63         if (! *ptr)
  64                 evconnlistener_disable(listener);
  65 }
  66 
  67 static void
  68 regress_pick_a_port(void *arg)
  69 {
  70         struct basic_test_data *data = arg;
  71         struct event_base *base = data->base;
  72         struct evconnlistener *listener1 = NULL, *listener2 = NULL;
  73         struct sockaddr_in sin;
  74         int count1 = 2, count2 = 1;
  75         struct sockaddr_storage ss1, ss2;
  76         struct sockaddr_in *sin1, *sin2;
  77         ev_socklen_t slen1 = sizeof(ss1), slen2 = sizeof(ss2);
  78         unsigned int flags =
  79             LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC;
  80 
  81         evutil_socket_t fd1 = -1, fd2 = -1, fd3 = -1;
  82 
  83         if (data->setup_data && strstr((char*)data->setup_data, "ts")) {
  84                 flags |= LEV_OPT_THREADSAFE;
  85         }
  86 
  87         memset(&sin, 0, sizeof(sin));
  88         sin.sin_family = AF_INET;
  89         sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
  90         sin.sin_port = 0; /* "You pick!" */
  91 
  92         listener1 = evconnlistener_new_bind(base, acceptcb, &count1,
  93             flags, -1, (struct sockaddr *)&sin, sizeof(sin));
  94         tt_assert(listener1);
  95         listener2 = evconnlistener_new_bind(base, acceptcb, &count2,
  96             flags, -1, (struct sockaddr *)&sin, sizeof(sin));
  97         tt_assert(listener2);
  98 
  99         tt_int_op(evconnlistener_get_fd(listener1), >=, 0);
 100         tt_int_op(evconnlistener_get_fd(listener2), >=, 0);
 101         tt_assert(getsockname(evconnlistener_get_fd(listener1),
 102                 (struct sockaddr*)&ss1, &slen1) == 0);
 103         tt_assert(getsockname(evconnlistener_get_fd(listener2),
 104                 (struct sockaddr*)&ss2, &slen2) == 0);
 105         tt_int_op(ss1.ss_family, ==, AF_INET);
 106         tt_int_op(ss2.ss_family, ==, AF_INET);
 107 
 108         sin1 = (struct sockaddr_in*)&ss1;
 109         sin2 = (struct sockaddr_in*)&ss2;
 110         tt_int_op(ntohl(sin1->sin_addr.s_addr), ==, 0x7f000001);
 111         tt_int_op(ntohl(sin2->sin_addr.s_addr), ==, 0x7f000001);
 112         tt_int_op(sin1->sin_port, !=, sin2->sin_port);
 113 
 114         tt_ptr_op(evconnlistener_get_base(listener1), ==, base);
 115         tt_ptr_op(evconnlistener_get_base(listener2), ==, base);
 116 
 117         fd1 = fd2 = fd3 = -1;
 118         evutil_socket_connect(&fd1, (struct sockaddr*)&ss1, slen1);
 119         evutil_socket_connect(&fd2, (struct sockaddr*)&ss1, slen1);
 120         evutil_socket_connect(&fd3, (struct sockaddr*)&ss2, slen2);
 121 
 122 #ifdef WIN32
 123         Sleep(100); /* XXXX this is a stupid stopgap. */
 124 #endif
 125         event_base_dispatch(base);
 126 
 127         tt_int_op(count1, ==, 0);
 128         tt_int_op(count2, ==, 0);
 129 
 130 end:
 131         if (fd1>=0)
 132                 EVUTIL_CLOSESOCKET(fd1);
 133         if (fd2>=0)
 134                 EVUTIL_CLOSESOCKET(fd2);
 135         if (fd3>=0)
 136                 EVUTIL_CLOSESOCKET(fd3);
 137         if (listener1)
 138                 evconnlistener_free(listener1);
 139         if (listener2)
 140                 evconnlistener_free(listener2);
 141 }
 142 
 143 static void
 144 errorcb(struct evconnlistener *lis, void *data_)
 145 {
 146         int *data = data_;
 147         *data = 1000;
 148         evconnlistener_disable(lis);
 149 }
 150 
 151 static void
 152 regress_listener_error(void *arg)
 153 {
 154         struct basic_test_data *data = arg;
 155         struct event_base *base = data->base;
 156         struct evconnlistener *listener = NULL;
 157         int count = 1;
 158         unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE;
 159 
 160         if (data->setup_data && strstr((char*)data->setup_data, "ts")) {
 161                 flags |= LEV_OPT_THREADSAFE;
 162         }
 163 
 164         /* send, so that pair[0] will look 'readable'*/
 165         tt_int_op(send(data->pair[1], "hello", 5, 0), >, 0);
 166 
 167         /* Start a listener with a bogus socket. */
 168         listener = evconnlistener_new(base, acceptcb, &count,
 169             flags, 0,
 170             data->pair[0]);
 171         tt_assert(listener);
 172 
 173         evconnlistener_set_error_cb(listener, errorcb);
 174 
 175         tt_assert(listener);
 176 
 177         event_base_dispatch(base);
 178         tt_int_op(count,==,1000); /* set by error cb */
 179 
 180 end:
 181         if (listener)
 182                 evconnlistener_free(listener);
 183 }
 184 
 185 struct testcase_t listener_testcases[] = {
 186 
 187         { "randport", regress_pick_a_port, TT_FORK|TT_NEED_BASE,
 188           &basic_setup, NULL},
 189 
 190         { "randport_ts", regress_pick_a_port, TT_FORK|TT_NEED_BASE,
 191           &basic_setup, (char*)"ts"},
 192 
 193         { "error", regress_listener_error,
 194           TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR,
 195           &basic_setup, NULL},
 196 
 197         { "error_ts", regress_listener_error,
 198           TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR,
 199           &basic_setup, (char*)"ts"},
 200 
 201         END_OF_TESTCASES,
 202 };
 203 
 204 struct testcase_t listener_iocp_testcases[] = {
 205         { "randport", regress_pick_a_port,
 206           TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP,
 207           &basic_setup, NULL},
 208 
 209         { "error", regress_listener_error,
 210           TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR|TT_ENABLE_IOCP,
 211           &basic_setup, NULL},
 212 
 213         END_OF_TESTCASES,
 214 };

/* [<][>][^][v][top][bottom][index][help] */