1 /* $NetBSD: sock_test.c,v 1.8 2014/12/10 04:37:53 christos Exp $ */
4 * Copyright (C) 2004, 2007, 2008, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: sock_test.c,v 1.55 2008/07/23 23:27:54 marka Exp */
29 #include <isc/print.h>
31 #include <isc/socket.h>
32 #include <isc/timer.h>
36 isc_taskmgr_t
*manager
;
39 my_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
40 char *name
= event
->ev_arg
;
42 printf("shutdown %s (%p)\n", name
, task
);
44 isc_event_free(&event
);
48 my_send(isc_task_t
*task
, isc_event_t
*event
) {
50 isc_socketevent_t
*dev
;
52 sock
= event
->ev_sender
;
53 dev
= (isc_socketevent_t
*)event
;
55 printf("my_send: %s task %p\n\t(sock %p, base %p, length %d, n %d, "
57 (char *)(event
->ev_arg
), task
, sock
,
58 dev
->region
.base
, dev
->region
.length
,
61 if (dev
->result
!= ISC_R_SUCCESS
) {
62 isc_socket_detach(&sock
);
63 isc_task_shutdown(task
);
66 isc_mem_put(mctx
, dev
->region
.base
, dev
->region
.length
);
68 isc_event_free(&event
);
72 my_recv(isc_task_t
*task
, isc_event_t
*event
) {
74 isc_socketevent_t
*dev
;
79 sock
= event
->ev_sender
;
80 dev
= (isc_socketevent_t
*)event
;
82 printf("Socket %s (sock %p, base %p, length %d, n %d, result %d)\n",
83 (char *)(event
->ev_arg
), sock
,
84 dev
->region
.base
, dev
->region
.length
,
86 if (dev
->address
.type
.sa
.sa_family
== AF_INET6
) {
87 inet_ntop(AF_INET6
, &dev
->address
.type
.sin6
.sin6_addr
,
89 printf("\tFrom: %s port %d\n", host
,
90 ntohs(dev
->address
.type
.sin6
.sin6_port
));
92 inet_ntop(AF_INET
, &dev
->address
.type
.sin
.sin_addr
,
94 printf("\tFrom: %s port %d\n", host
,
95 ntohs(dev
->address
.type
.sin
.sin_port
));
98 if (dev
->result
!= ISC_R_SUCCESS
) {
99 isc_socket_detach(&sock
);
101 isc_mem_put(mctx
, dev
->region
.base
,
103 isc_event_free(&event
);
105 isc_task_shutdown(task
);
110 * Echo the data back.
112 if (strcmp(event
->ev_arg
, "so2") != 0) {
113 region
= dev
->region
;
114 sprintf(buf
, "\r\nReceived: %.*s\r\n\r\n",
115 (int)dev
->n
, (char *)region
.base
);
116 region
.base
= isc_mem_get(mctx
, strlen(buf
) + 1);
117 region
.length
= strlen(buf
) + 1;
118 strcpy((char *)region
.base
, buf
); /* strcpy is safe */
119 isc_socket_send(sock
, ®ion
, task
, my_send
, event
->ev_arg
);
121 region
= dev
->region
;
122 printf("\r\nReceived: %.*s\r\n\r\n",
123 (int)dev
->n
, (char *)region
.base
);
126 isc_socket_recv(sock
, &dev
->region
, 1, task
, my_recv
, event
->ev_arg
);
128 isc_event_free(&event
);
132 my_http_get(isc_task_t
*task
, isc_event_t
*event
) {
134 isc_socketevent_t
*dev
;
136 sock
= event
->ev_sender
;
137 dev
= (isc_socketevent_t
*)event
;
139 printf("my_http_get: %s task %p\n\t(sock %p, base %p, length %d, "
140 "n %d, result %d)\n",
141 (char *)(event
->ev_arg
), task
, sock
,
142 dev
->region
.base
, dev
->region
.length
,
143 dev
->n
, dev
->result
);
145 if (dev
->result
!= ISC_R_SUCCESS
) {
146 isc_socket_detach(&sock
);
147 isc_task_shutdown(task
);
148 isc_event_free(&event
);
152 isc_socket_recv(sock
, &dev
->region
, 1, task
, my_recv
, event
->ev_arg
);
154 isc_event_free(&event
);
158 my_connect(isc_task_t
*task
, isc_event_t
*event
) {
160 isc_socket_connev_t
*dev
;
164 sock
= event
->ev_sender
;
165 dev
= (isc_socket_connev_t
*)event
;
167 printf("%s: Connection result: %d\n", (char *)(event
->ev_arg
),
170 if (dev
->result
!= ISC_R_SUCCESS
) {
171 isc_socket_detach(&sock
);
172 isc_event_free(&event
);
173 isc_task_shutdown(task
);
178 * Send a GET string, and set up to receive (and just display)
181 strcpy(buf
, "GET / HTTP/1.1\r\nHost: www.flame.org\r\n"
182 "Connection: Close\r\n\r\n");
183 region
.base
= isc_mem_get(mctx
, strlen(buf
) + 1);
184 region
.length
= strlen(buf
) + 1;
185 strcpy((char *)region
.base
, buf
); /* This strcpy is safe. */
187 isc_socket_send(sock
, ®ion
, task
, my_http_get
, event
->ev_arg
);
189 isc_event_free(&event
);
193 my_listen(isc_task_t
*task
, isc_event_t
*event
) {
194 char *name
= event
->ev_arg
;
195 isc_socket_newconnev_t
*dev
;
197 isc_socket_t
*oldsock
;
200 dev
= (isc_socket_newconnev_t
*)event
;
202 printf("newcon %s (task %p, oldsock %p, newsock %p, result %d)\n",
203 name
, task
, event
->ev_sender
, dev
->newsocket
, dev
->result
);
206 if (dev
->result
== ISC_R_SUCCESS
) {
208 * Queue another listen on this socket.
210 RUNTIME_CHECK(isc_socket_accept(event
->ev_sender
, task
,
211 my_listen
, event
->ev_arg
)
214 region
.base
= isc_mem_get(mctx
, 20);
218 * Create a new task for this socket, and queue up a
222 RUNTIME_CHECK(isc_task_create(manager
, 0, &newtask
)
224 isc_socket_recv(dev
->newsocket
, ®ion
, 1,
225 newtask
, my_recv
, event
->ev_arg
);
226 isc_task_detach(&newtask
);
228 printf("detaching from socket %p\n", event
->ev_sender
);
229 oldsock
= event
->ev_sender
;
231 isc_socket_detach(&oldsock
);
233 isc_event_free(&event
);
234 isc_task_shutdown(task
);
238 isc_event_free(&event
);
242 timeout(isc_task_t
*task
, isc_event_t
*event
) {
243 isc_socket_t
*sock
= event
->ev_arg
;
245 printf("Timeout, canceling IO on socket %p (task %p)\n", sock
, task
);
247 isc_socket_cancel(sock
, NULL
, ISC_SOCKCANCEL_ALL
);
248 isc_timer_detach((isc_timer_t
**)&event
->ev_sender
);
249 isc_event_free(&event
);
252 static char one
[] = "1";
253 static char two
[] = "2";
254 static char xso1
[] = "so1";
255 static char xso2
[] = "so2";
258 main(int argc
, char *argv
[]) {
260 isc_timermgr_t
*timgr
;
262 isc_interval_t interval
;
264 unsigned int workers
;
265 isc_socketmgr_t
*socketmgr
;
266 isc_socket_t
*so1
, *so2
;
267 isc_sockaddr_t sockaddr
;
269 struct in6_addr in6a
;
274 workers
= atoi(argv
[1]);
281 printf("%d workers\n", workers
);
283 if (isc_net_probeipv6() == ISC_R_SUCCESS
)
289 * EVERYTHING needs a memory context.
292 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx
) == ISC_R_SUCCESS
);
295 * The task manager is independent (other than memory context)
298 RUNTIME_CHECK(isc_taskmgr_create(mctx
, workers
, 0, &manager
) ==
302 * Timer manager depends only on the memory context as well.
305 RUNTIME_CHECK(isc_timermgr_create(mctx
, &timgr
) == ISC_R_SUCCESS
);
308 RUNTIME_CHECK(isc_task_create(manager
, 0, &t1
) == ISC_R_SUCCESS
);
310 RUNTIME_CHECK(isc_task_create(manager
, 0, &t2
) == ISC_R_SUCCESS
);
311 RUNTIME_CHECK(isc_task_onshutdown(t1
, my_shutdown
, one
) ==
313 RUNTIME_CHECK(isc_task_onshutdown(t2
, my_shutdown
, two
) ==
316 printf("task 1 = %p\n", t1
);
317 printf("task 2 = %p\n", t2
);
320 RUNTIME_CHECK(isc_socketmgr_create(mctx
, &socketmgr
) == ISC_R_SUCCESS
);
323 * Open up a listener socket.
327 if (pf
== PF_INET6
) {
329 isc_sockaddr_fromin6(&sockaddr
, &in6a
, 5544);
331 ina
.s_addr
= INADDR_ANY
;
332 isc_sockaddr_fromin(&sockaddr
, &ina
, 5544);
334 RUNTIME_CHECK(isc_socket_create(socketmgr
, pf
, isc_sockettype_tcp
,
335 &so1
) == ISC_R_SUCCESS
);
336 result
= isc_socket_bind(so1
, &sockaddr
, ISC_SOCKET_REUSEADDRESS
);
337 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
338 RUNTIME_CHECK(isc_socket_listen(so1
, 0) == ISC_R_SUCCESS
);
341 * Queue up the first accept event.
343 RUNTIME_CHECK(isc_socket_accept(so1
, t1
, my_listen
, xso1
)
345 isc_time_settoepoch(&expires
);
346 isc_interval_set(&interval
, 10, 0);
348 RUNTIME_CHECK(isc_timer_create(timgr
, isc_timertype_once
, &expires
,
349 &interval
, t1
, timeout
, so1
, &ti1
) ==
353 * Open up a socket that will connect to www.flame.org, port 80.
357 ina
.s_addr
= inet_addr("204.152.184.97");
358 if (0 && pf
== PF_INET6
)
359 isc_sockaddr_v6fromin(&sockaddr
, &ina
, 80);
361 isc_sockaddr_fromin(&sockaddr
, &ina
, 80);
362 RUNTIME_CHECK(isc_socket_create(socketmgr
, isc_sockaddr_pf(&sockaddr
),
364 &so2
) == ISC_R_SUCCESS
);
366 RUNTIME_CHECK(isc_socket_connect(so2
, &sockaddr
, t2
,
367 my_connect
, xso2
) == ISC_R_SUCCESS
);
370 * Detaching these is safe, since the socket will attach to the
371 * task for any outstanding requests.
373 isc_task_detach(&t1
);
374 isc_task_detach(&t2
);
377 * Wait a short while.
385 fprintf(stderr
, "Destroying socket manager\n");
386 isc_socketmgr_destroy(&socketmgr
);
388 fprintf(stderr
, "Destroying timer manager\n");
389 isc_timermgr_destroy(&timgr
);
391 fprintf(stderr
, "Destroying task manager\n");
392 isc_taskmgr_destroy(&manager
);
394 isc_mem_stats(mctx
, stdout
);
395 isc_mem_destroy(&mctx
);