1/* 2 * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <atf-c.h> 24 25#include <unistd.h> 26#include <time.h> 27 28#include <isc/socket.h> 29 30#include "../task_p.h" 31#include "isctest.h" 32 33/* 34 * Helper functions 35 */ 36typedef struct { 37 isc_boolean_t done; 38 isc_result_t result; 39} completion_t; 40 41static void 42completion_init(completion_t *completion) { 43 completion->done = ISC_FALSE; 44} 45 46static void 47event_done(isc_task_t *task, isc_event_t *event) { 48 isc_socketevent_t *dev; 49 completion_t *completion = event->ev_arg; 50 51 UNUSED(task); 52 53 dev = (isc_socketevent_t *) event; 54 completion->result = dev->result; 55 completion->done = ISC_TRUE; 56 isc_event_free(&event); 57} 58 59static isc_result_t 60waitfor(completion_t *completion) { 61 int i = 0; 62 while (!completion->done && i++ < 5000) { 63#ifndef ISC_PLATFORM_USETHREADS 64 while (isc__taskmgr_ready(taskmgr)) 65 isc__taskmgr_dispatch(taskmgr); 66#endif 67 isc_test_nap(1000); 68 } 69 if (completion->done) 70 return (ISC_R_SUCCESS); 71 return (ISC_R_FAILURE); 72} 73 74/* 75 * Individual unit tests 76 */ 77 78/* Test UDP sendto/recv (IPv4) */ 79ATF_TC(udp_sendto); 80ATF_TC_HEAD(udp_sendto, tc) { 81 atf_tc_set_md_var(tc, "descr", "UDP sendto/recv"); 82} 83ATF_TC_BODY(udp_sendto, tc) { 84 isc_result_t result; 85 isc_sockaddr_t addr1, addr2; 86 struct in_addr in; 87 isc_socket_t *s1 = NULL, *s2 = NULL; 88 isc_task_t *task = NULL; 89 char sendbuf[BUFSIZ], recvbuf[BUFSIZ]; 90 completion_t completion; 91 isc_region_t r; 92 93 UNUSED(tc); 94 95 result = isc_test_begin(NULL, ISC_TRUE); 96 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 97 98 /* 99 * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to 100 * each other. 101 */ 102 in.s_addr = inet_addr("127.0.0.1"); 103 isc_sockaddr_fromin(&addr1, &in, 5444); 104 isc_sockaddr_fromin(&addr2, &in, 5445); 105 106 result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1); 107 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 108 result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS); 109 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 110 111 result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2); 112 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 113 result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS); 114 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 115 116 result = isc_task_create(taskmgr, 0, &task); 117 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 118 119 strcpy(sendbuf, "Hello"); 120 r.base = (void *) sendbuf; 121 r.length = strlen(sendbuf) + 1; 122 123 completion_init(&completion); 124 result = isc_socket_sendto(s1, &r, task, event_done, &completion, 125 &addr2, NULL); 126 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 127 waitfor(&completion); 128 ATF_CHECK(completion.done); 129 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 130 131 r.base = (void *) recvbuf; 132 r.length = BUFSIZ; 133 completion_init(&completion); 134 result = isc_socket_recv(s2, &r, 1, task, event_done, &completion); 135 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 136 waitfor(&completion); 137 ATF_CHECK(completion.done); 138 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 139 ATF_CHECK_STREQ(recvbuf, "Hello"); 140 141 isc_task_detach(&task); 142 143 isc_socket_detach(&s1); 144 isc_socket_detach(&s2); 145 146 isc_test_end(); 147} 148 149/* Test UDP sendto/recv with duplicated socket */ 150ATF_TC(udp_dup); 151ATF_TC_HEAD(udp_dup, tc) { 152 atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv"); 153} 154ATF_TC_BODY(udp_dup, tc) { 155 isc_result_t result; 156 isc_sockaddr_t addr1, addr2; 157 struct in_addr in; 158 isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL; 159 isc_task_t *task = NULL; 160 char sendbuf[BUFSIZ], recvbuf[BUFSIZ]; 161 completion_t completion; 162 isc_region_t r; 163 164 UNUSED(tc); 165 166 result = isc_test_begin(NULL, ISC_TRUE); 167 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 168 169 /* 170 * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to 171 * each other. 172 */ 173 in.s_addr = inet_addr("127.0.0.1"); 174 isc_sockaddr_fromin(&addr1, &in, 5444); 175 isc_sockaddr_fromin(&addr2, &in, 5445); 176 177 result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1); 178 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 179 result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS); 180 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 181 182 result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2); 183 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 184 result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS); 185 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 186 187 result = isc_socket_dup(s2, &s3); 188 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 189 190 result = isc_task_create(taskmgr, 0, &task); 191 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 192 193 strcpy(sendbuf, "Hello"); 194 r.base = (void *) sendbuf; 195 r.length = strlen(sendbuf) + 1; 196 197 completion_init(&completion); 198 result = isc_socket_sendto(s1, &r, task, event_done, &completion, 199 &addr2, NULL); 200 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 201 waitfor(&completion); 202 ATF_CHECK(completion.done); 203 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 204 205 strcpy(sendbuf, "World"); 206 r.base = (void *) sendbuf; 207 r.length = strlen(sendbuf) + 1; 208 209 completion_init(&completion); 210 result = isc_socket_sendto(s1, &r, task, event_done, &completion, 211 &addr2, NULL); 212 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 213 waitfor(&completion); 214 ATF_CHECK(completion.done); 215 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 216 217 r.base = (void *) recvbuf; 218 r.length = BUFSIZ; 219 completion_init(&completion); 220 result = isc_socket_recv(s2, &r, 1, task, event_done, &completion); 221 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 222 waitfor(&completion); 223 ATF_CHECK(completion.done); 224 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 225 ATF_CHECK_STREQ(recvbuf, "Hello"); 226 227 r.base = (void *) recvbuf; 228 r.length = BUFSIZ; 229 completion_init(&completion); 230 result = isc_socket_recv(s3, &r, 1, task, event_done, &completion); 231 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 232 waitfor(&completion); 233 ATF_CHECK(completion.done); 234 ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); 235 ATF_CHECK_STREQ(recvbuf, "World"); 236 237 isc_task_detach(&task); 238 239 isc_socket_detach(&s1); 240 isc_socket_detach(&s2); 241 isc_socket_detach(&s3); 242 243 isc_test_end(); 244} 245 246/* 247 * Main 248 */ 249ATF_TP_ADD_TCS(tp) { 250 ATF_TP_ADD_TC(tp, udp_sendto); 251 ATF_TP_ADD_TC(tp, udp_dup); 252 253 return (atf_no_error()); 254} 255 256