sock_test.c 9.6 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
2
 * Copyright (C) 1998-2001, 2004, 2007, 2008, 2012-2016  Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
Bob Halley's avatar
Bob Halley committed
7
 */
8

9
/* $Id: sock_test.c,v 1.55 2008/07/23 23:27:54 marka Exp $ */
David Lawrence's avatar
David Lawrence committed
10

Bob Halley's avatar
Bob Halley committed
11 12
#include <config.h>

13
#include <stdlib.h>
Brian Wellington's avatar
Brian Wellington committed
14
#include <string.h>
15 16
#include <unistd.h>

Bob Halley's avatar
Bob Halley committed
17
#include <isc/mem.h>
18
#include <isc/print.h>
19 20
#include <isc/task.h>
#include <isc/socket.h>
Michael Graff's avatar
Michael Graff committed
21
#include <isc/timer.h>
Brian Wellington's avatar
Brian Wellington committed
22
#include <isc/util.h>
23

Michael Graff's avatar
Michael Graff committed
24 25
isc_mem_t *mctx;
isc_taskmgr_t *manager;
Michael Graff's avatar
Michael Graff committed
26

27
static void
28
my_shutdown(isc_task_t *task, isc_event_t *event) {
29
	char *name = event->ev_arg;
30 31 32 33

	printf("shutdown %s (%p)\n", name, task);
	fflush(stdout);
	isc_event_free(&event);
Michael Graff's avatar
Michael Graff committed
34 35
}

36
static void
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
my_send(isc_task_t *task, isc_event_t *event) {
	isc_socket_t *sock;
	isc_socketevent_t *dev;

	sock = event->ev_sender;
	dev = (isc_socketevent_t *)event;

	printf("my_send: %s task %p\n\t(sock %p, base %p, length %d, n %d, "
	       "result %d)\n",
	       (char *)(event->ev_arg), task, sock,
	       dev->region.base, dev->region.length,
	       dev->n, dev->result);

	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);
		isc_task_shutdown(task);
	}

55 56
	if (dev->region.base != NULL)
		isc_mem_put(mctx, dev->region.base, dev->region.length);
57 58 59 60 61 62

	isc_event_free(&event);
}

static void
my_recv(isc_task_t *task, isc_event_t *event) {
Bob Halley's avatar
Bob Halley committed
63 64 65
	isc_socket_t *sock;
	isc_socketevent_t *dev;
	isc_region_t region;
Michael Graff's avatar
Michael Graff committed
66
	char buf[1024];
Michael Graff's avatar
Michael Graff committed
67
	char host[256];
Michael Graff's avatar
Michael Graff committed
68

69
	sock = event->ev_sender;
Bob Halley's avatar
Bob Halley committed
70
	dev = (isc_socketevent_t *)event;
Michael Graff's avatar
Michael Graff committed
71 72

	printf("Socket %s (sock %p, base %p, length %d, n %d, result %d)\n",
73
	       (char *)(event->ev_arg), sock,
Michael Graff's avatar
Michael Graff committed
74 75
	       dev->region.base, dev->region.length,
	       dev->n, dev->result);
Michael Graff's avatar
Michael Graff committed
76 77
	if (dev->address.type.sa.sa_family == AF_INET6) {
		inet_ntop(AF_INET6, &dev->address.type.sin6.sin6_addr,
Andreas Gustafsson's avatar
Andreas Gustafsson committed
78
			  host, sizeof(host));
Michael Graff's avatar
Michael Graff committed
79 80 81 82
		printf("\tFrom: %s port %d\n", host,
		       ntohs(dev->address.type.sin6.sin6_port));
	} else {
		inet_ntop(AF_INET, &dev->address.type.sin.sin_addr,
Andreas Gustafsson's avatar
Andreas Gustafsson committed
83
			  host, sizeof(host));
Michael Graff's avatar
Michael Graff committed
84 85 86
		printf("\tFrom: %s port %d\n", host,
		       ntohs(dev->address.type.sin.sin_port));
	}
Michael Graff's avatar
Michael Graff committed
87 88 89 90

	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);

91 92
		if (dev->region.base != NULL)
			isc_mem_put(mctx, dev->region.base, dev->region.length);
Michael Graff's avatar
Michael Graff committed
93 94
		isc_event_free(&event);

Michael Graff's avatar
Michael Graff committed
95
		isc_task_shutdown(task);
96
		return;
Michael Graff's avatar
Michael Graff committed
97 98 99
	}

	/*
100
	 * Echo the data back.
Michael Graff's avatar
Michael Graff committed
101
	 */
102
	if (strcmp(event->ev_arg, "so2") != 0) {
Michael Graff's avatar
Michael Graff committed
103
		region = dev->region;
104
		sprintf(buf, "\r\nReceived: %.*s\r\n\r\n",
105
			(int)dev->n, (char *)region.base);
Bob Halley's avatar
Bob Halley committed
106
		region.base = isc_mem_get(mctx, strlen(buf) + 1);
107 108 109 110 111
		if (region.base != NULL) {
			region.length = strlen(buf) + 1;
			strcpy((char *)region.base, buf);  /* strcpy is safe */
		} else
			region.length = 0;
112
		isc_socket_send(sock, &region, task, my_send, event->ev_arg);
Michael Graff's avatar
Michael Graff committed
113 114
	} else {
		region = dev->region;
115
		printf("\r\nReceived: %.*s\r\n\r\n",
116
		       (int)dev->n, (char *)region.base);
Michael Graff's avatar
Michael Graff committed
117 118
	}

119
	isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
Michael Graff's avatar
Michael Graff committed
120 121 122 123

	isc_event_free(&event);
}

124
static void
125
my_http_get(isc_task_t *task, isc_event_t *event) {
Bob Halley's avatar
Bob Halley committed
126 127
	isc_socket_t *sock;
	isc_socketevent_t *dev;
128

129
	sock = event->ev_sender;
Bob Halley's avatar
Bob Halley committed
130
	dev = (isc_socketevent_t *)event;
131

132 133
	printf("my_http_get: %s task %p\n\t(sock %p, base %p, length %d, "
	       "n %d, result %d)\n",
134
	       (char *)(event->ev_arg), task, sock,
135 136
	       dev->region.base, dev->region.length,
	       dev->n, dev->result);
Michael Graff's avatar
Michael Graff committed
137

Michael Graff's avatar
Michael Graff committed
138 139 140
	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);
		isc_task_shutdown(task);
141 142
		if (dev->region.base != NULL)
			isc_mem_put(mctx, dev->region.base, dev->region.length);
Michael Graff's avatar
Michael Graff committed
143 144 145 146
		isc_event_free(&event);
		return;
	}

147
	isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
Michael Graff's avatar
Michael Graff committed
148 149 150 151

	isc_event_free(&event);
}

152
static void
153
my_connect(isc_task_t *task, isc_event_t *event) {
Bob Halley's avatar
Bob Halley committed
154 155 156
	isc_socket_t *sock;
	isc_socket_connev_t *dev;
	isc_region_t region;
Michael Graff's avatar
Michael Graff committed
157 158
	char buf[1024];

159
	sock = event->ev_sender;
Bob Halley's avatar
Bob Halley committed
160
	dev = (isc_socket_connev_t *)event;
Michael Graff's avatar
Michael Graff committed
161

162
	printf("%s: Connection result:  %d\n", (char *)(event->ev_arg),
Michael Graff's avatar
Michael Graff committed
163
	       dev->result);
164 165 166 167

	if (dev->result != ISC_R_SUCCESS) {
		isc_socket_detach(&sock);
		isc_event_free(&event);
Michael Graff's avatar
Michael Graff committed
168
		isc_task_shutdown(task);
169
		return;
170 171
	}

Michael Graff's avatar
Michael Graff committed
172
	/*
Michael Graff's avatar
Michael Graff committed
173 174
	 * Send a GET string, and set up to receive (and just display)
	 * the result.
Michael Graff's avatar
Michael Graff committed
175
	 */
Evan Hunt's avatar
Evan Hunt committed
176 177 178
	snprintf(buf, sizeof(buf),
		 "GET / HTTP/1.1\r\nHost: www.flame.org\r\n"
		 "Connection: Close\r\n\r\n");
Bob Halley's avatar
Bob Halley committed
179
	region.base = isc_mem_get(mctx, strlen(buf) + 1);
180 181 182
	if (region.base != NULL) {
		region.length = strlen(buf) + 1;
		strcpy((char *)region.base, buf);  /* This strcpy is safe. */
Evan Hunt's avatar
Evan Hunt committed
183
	} else {
184
		region.length = 0;
Evan Hunt's avatar
Evan Hunt committed
185
	}
186

187
	isc_socket_send(sock, &region, task, my_http_get, event->ev_arg);
Michael Graff's avatar
Michael Graff committed
188

189 190 191
	isc_event_free(&event);
}

192
static void
193
my_listen(isc_task_t *task, isc_event_t *event) {
194
	char *name = event->ev_arg;
Bob Halley's avatar
Bob Halley committed
195 196 197
	isc_socket_newconnev_t *dev;
	isc_region_t region;
	isc_socket_t *oldsock;
Michael Graff's avatar
Michael Graff committed
198
	isc_task_t *newtask;
Michael Graff's avatar
Michael Graff committed
199

Bob Halley's avatar
Bob Halley committed
200
	dev = (isc_socket_newconnev_t *)event;
201 202

	printf("newcon %s (task %p, oldsock %p, newsock %p, result %d)\n",
203
	       name, task, event->ev_sender, dev->newsocket, dev->result);
Michael Graff's avatar
Michael Graff committed
204 205
	fflush(stdout);

206 207
	if (dev->result == ISC_R_SUCCESS) {
		/*
208
		 * Queue another listen on this socket.
209
		 */
210 211 212
		RUNTIME_CHECK(isc_socket_accept(event->ev_sender, task,
						my_listen, event->ev_arg)
			      == ISC_R_SUCCESS);
213

Bob Halley's avatar
Bob Halley committed
214
		region.base = isc_mem_get(mctx, 20);
Michael Graff's avatar
Michael Graff committed
215
		region.length = 20;
216 217

		/*
Michael Graff's avatar
Michael Graff committed
218 219
		 * Create a new task for this socket, and queue up a
		 * recv on it.
220
		 */
Michael Graff's avatar
Michael Graff committed
221
		newtask = NULL;
Bob Halley's avatar
Bob Halley committed
222
		RUNTIME_CHECK(isc_task_create(manager, 0, &newtask)
Michael Graff's avatar
Michael Graff committed
223
			      == ISC_R_SUCCESS);
224
		isc_socket_recv(dev->newsocket, &region, 1,
225
				newtask, my_recv, event->ev_arg);
Michael Graff's avatar
Michael Graff committed
226
		isc_task_detach(&newtask);
227
	} else {
228 229
		printf("detaching from socket %p\n", event->ev_sender);
		oldsock = event->ev_sender;
Michael Graff's avatar
Michael Graff committed
230 231 232

		isc_socket_detach(&oldsock);

Michael Graff's avatar
Michael Graff committed
233
		isc_event_free(&event);
234 235
		isc_task_shutdown(task);
		return;
236
	}
Michael Graff's avatar
Michael Graff committed
237

238
	isc_event_free(&event);
Michael Graff's avatar
Michael Graff committed
239 240
}

241
static void
242
timeout(isc_task_t *task, isc_event_t *event) {
243
	isc_socket_t *sock = event->ev_arg;
Michael Graff's avatar
Michael Graff committed
244

Bob Halley's avatar
Bob Halley committed
245
	printf("Timeout, canceling IO on socket %p (task %p)\n", sock, task);
Michael Graff's avatar
Michael Graff committed
246 247

	isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_ALL);
248
	isc_timer_detach((isc_timer_t **)&event->ev_sender);
Michael Graff's avatar
Michael Graff committed
249
	isc_event_free(&event);
250 251
}

Mark Andrews's avatar
Mark Andrews committed
252 253 254 255 256
static char one[] = "1";
static char two[] = "2";
static char xso1[] = "so1";
static char xso2[] = "so2";

257
int
258
main(int argc, char *argv[]) {
Michael Graff's avatar
Michael Graff committed
259 260 261
	isc_task_t *t1, *t2;
	isc_timermgr_t *timgr;
	isc_time_t expires;
Bob Halley's avatar
Bob Halley committed
262
	isc_interval_t interval;
Michael Graff's avatar
Michael Graff committed
263
	isc_timer_t *ti1;
264
	unsigned int workers;
Bob Halley's avatar
Bob Halley committed
265 266 267
	isc_socketmgr_t *socketmgr;
	isc_socket_t *so1, *so2;
	isc_sockaddr_t sockaddr;
Bob Halley's avatar
Bob Halley committed
268 269 270 271
	struct in_addr ina;
	struct in6_addr in6a;
	isc_result_t result;
	int pf;
272

Mark Andrews's avatar
Mark Andrews committed
273
	if (argc > 1) {
274
		workers = atoi(argv[1]);
Mark Andrews's avatar
Mark Andrews committed
275 276 277 278 279
		if (workers < 1)
			workers = 1;
		if (workers > 8192)
			workers = 8192;
	} else
280 281 282
		workers = 2;
	printf("%d workers\n", workers);

283
	if (isc_net_probeipv6() == ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
284 285 286 287
		pf = PF_INET6;
	else
		pf = PF_INET;

Michael Graff's avatar
Michael Graff committed
288 289 290 291
	/*
	 * EVERYTHING needs a memory context.
	 */
	mctx = NULL;
Bob Halley's avatar
Bob Halley committed
292
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
293

Michael Graff's avatar
Michael Graff committed
294 295 296 297
	/*
	 * The task manager is independent (other than memory context)
	 */
	manager = NULL;
Bob Halley's avatar
Bob Halley committed
298 299
	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
		      ISC_R_SUCCESS);
300

Michael Graff's avatar
Michael Graff committed
301 302 303 304 305 306 307
	/*
	 * Timer manager depends only on the memory context as well.
	 */
	timgr = NULL;
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);

	t1 = NULL;
Bob Halley's avatar
Bob Halley committed
308
	RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
309
	t2 = NULL;
Bob Halley's avatar
Bob Halley committed
310
	RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
Mark Andrews's avatar
Mark Andrews committed
311
	RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, one) ==
Bob Halley's avatar
Bob Halley committed
312
		      ISC_R_SUCCESS);
Mark Andrews's avatar
Mark Andrews committed
313
	RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, two) ==
Bob Halley's avatar
Bob Halley committed
314
		      ISC_R_SUCCESS);
315 316 317 318 319

	printf("task 1 = %p\n", t1);
	printf("task 2 = %p\n", t2);

	socketmgr = NULL;
Bob Halley's avatar
Bob Halley committed
320
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
321 322

	/*
323
	 * Open up a listener socket.
Michael Graff's avatar
Michael Graff committed
324
	 */
325
	so1 = NULL;
Bob Halley's avatar
Bob Halley committed
326 327 328 329 330 331 332 333 334 335

	if (pf == PF_INET6) {
		in6a = in6addr_any;
		isc_sockaddr_fromin6(&sockaddr, &in6a, 5544);
	} else {
		ina.s_addr = INADDR_ANY;
		isc_sockaddr_fromin(&sockaddr, &ina, 5544);
	}
	RUNTIME_CHECK(isc_socket_create(socketmgr, pf, isc_sockettype_tcp,
					&so1) == ISC_R_SUCCESS);
336
	result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS);
Bob Halley's avatar
Bob Halley committed
337
	RUNTIME_CHECK(result == ISC_R_SUCCESS);
Bob Halley's avatar
Bob Halley committed
338
	RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS);
339

Michael Graff's avatar
Michael Graff committed
340
	/*
341
	 * Queue up the first accept event.
Michael Graff's avatar
Michael Graff committed
342
	 */
Mark Andrews's avatar
Mark Andrews committed
343
	RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, xso1)
David Lawrence's avatar
David Lawrence committed
344
		      == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
345
	isc_time_settoepoch(&expires);
Michael Graff's avatar
Michael Graff committed
346
	isc_interval_set(&interval, 10, 0);
Michael Graff's avatar
Michael Graff committed
347
	ti1 = NULL;
Bob Halley's avatar
Bob Halley committed
348 349 350
	RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
				       &interval, t1, timeout, so1, &ti1) ==
		      ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
351

Michael Graff's avatar
Michael Graff committed
352
	/*
353
	 * Open up a socket that will connect to www.flame.org, port 80.
Michael Graff's avatar
Michael Graff committed
354 355
	 * Why not.  :)
	 */
356
	so2 = NULL;
Michael Graff's avatar
Michael Graff committed
357 358
	ina.s_addr = inet_addr("204.152.184.97");
	if (0 && pf == PF_INET6)
Bob Halley's avatar
Bob Halley committed
359 360 361 362 363
		isc_sockaddr_v6fromin(&sockaddr, &ina, 80);
	else
		isc_sockaddr_fromin(&sockaddr, &ina, 80);
	RUNTIME_CHECK(isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr),
					isc_sockettype_tcp,
Bob Halley's avatar
Bob Halley committed
364
					&so2) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
365

Bob Halley's avatar
Bob Halley committed
366
	RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2,
Mark Andrews's avatar
Mark Andrews committed
367
					 my_connect, xso2) == ISC_R_SUCCESS);
368

Michael Graff's avatar
Michael Graff committed
369 370 371 372
	/*
	 * Detaching these is safe, since the socket will attach to the
	 * task for any outstanding requests.
	 */
Michael Graff's avatar
Michael Graff committed
373 374 375
	isc_task_detach(&t1);
	isc_task_detach(&t2);

Michael Graff's avatar
Michael Graff committed
376
	/*
377
	 * Wait a short while.
Michael Graff's avatar
Michael Graff committed
378
	 */
379
#ifndef WIN32
Michael Graff's avatar
Michael Graff committed
380
	sleep(10);
381 382 383
#else
	Sleep(10000);
#endif
Michael Graff's avatar
Michael Graff committed
384 385

	fprintf(stderr, "Destroying socket manager\n");
386
	isc_socketmgr_destroy(&socketmgr);
Michael Graff's avatar
Michael Graff committed
387

Michael Graff's avatar
Michael Graff committed
388
	fprintf(stderr, "Destroying timer manager\n");
Michael Graff's avatar
Michael Graff committed
389 390
	isc_timermgr_destroy(&timgr);

Michael Graff's avatar
Michael Graff committed
391
	fprintf(stderr, "Destroying task manager\n");
392
	isc_taskmgr_destroy(&manager);
Michael Graff's avatar
Michael Graff committed
393

394
	isc_mem_stats(mctx, stdout);
Bob Halley's avatar
Bob Halley committed
395
	isc_mem_destroy(&mctx);
396 397 398

	return (0);
}