4 * Copyright (C) 2004, 2007, 2008 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 isc_socket_accept(event
->ev_sender
, task
, my_listen
,
213 region
.base
= isc_mem_get(mctx
, 20);
217 * Create a new task for this socket, and queue up a
221 RUNTIME_CHECK(isc_task_create(manager
, 0, &newtask
)
223 isc_socket_recv(dev
->newsocket
, ®ion
, 1,
224 newtask
, my_recv
, event
->ev_arg
);
225 isc_task_detach(&newtask
);
227 printf("detaching from socket %p\n", event
->ev_sender
);
228 oldsock
= event
->ev_sender
;
230 isc_socket_detach(&oldsock
);
232 isc_event_free(&event
);
233 isc_task_shutdown(task
);
237 isc_event_free(&event
);
241 timeout(isc_task_t
*task
, isc_event_t
*event
) {
242 isc_socket_t
*sock
= event
->ev_arg
;
244 printf("Timeout, canceling IO on socket %p (task %p)\n", sock
, task
);
246 isc_socket_cancel(sock
, NULL
, ISC_SOCKCANCEL_ALL
);
247 isc_timer_detach((isc_timer_t
**)&event
->ev_sender
);
248 isc_event_free(&event
);
252 main(int argc
, char *argv
[]) {
254 isc_timermgr_t
*timgr
;
256 isc_interval_t interval
;
258 unsigned int workers
;
259 isc_socketmgr_t
*socketmgr
;
260 isc_socket_t
*so1
, *so2
;
261 isc_sockaddr_t sockaddr
;
263 struct in6_addr in6a
;
268 workers
= atoi(argv
[1]);
271 printf("%d workers\n", workers
);
273 if (isc_net_probeipv6() == ISC_R_SUCCESS
)
279 * EVERYTHING needs a memory context.
282 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx
) == ISC_R_SUCCESS
);
285 * The task manager is independent (other than memory context)
288 RUNTIME_CHECK(isc_taskmgr_create(mctx
, workers
, 0, &manager
) ==
292 * Timer manager depends only on the memory context as well.
295 RUNTIME_CHECK(isc_timermgr_create(mctx
, &timgr
) == ISC_R_SUCCESS
);
298 RUNTIME_CHECK(isc_task_create(manager
, 0, &t1
) == ISC_R_SUCCESS
);
300 RUNTIME_CHECK(isc_task_create(manager
, 0, &t2
) == ISC_R_SUCCESS
);
301 RUNTIME_CHECK(isc_task_onshutdown(t1
, my_shutdown
, "1") ==
303 RUNTIME_CHECK(isc_task_onshutdown(t2
, my_shutdown
, "2") ==
306 printf("task 1 = %p\n", t1
);
307 printf("task 2 = %p\n", t2
);
310 RUNTIME_CHECK(isc_socketmgr_create(mctx
, &socketmgr
) == ISC_R_SUCCESS
);
313 * Open up a listener socket.
317 if (pf
== PF_INET6
) {
319 isc_sockaddr_fromin6(&sockaddr
, &in6a
, 5544);
321 ina
.s_addr
= INADDR_ANY
;
322 isc_sockaddr_fromin(&sockaddr
, &ina
, 5544);
324 RUNTIME_CHECK(isc_socket_create(socketmgr
, pf
, isc_sockettype_tcp
,
325 &so1
) == ISC_R_SUCCESS
);
326 result
= isc_socket_bind(so1
, &sockaddr
, ISC_SOCKET_REUSEADDRESS
);
327 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
328 RUNTIME_CHECK(isc_socket_listen(so1
, 0) == ISC_R_SUCCESS
);
331 * Queue up the first accept event.
333 RUNTIME_CHECK(isc_socket_accept(so1
, t1
, my_listen
, "so1")
335 isc_time_settoepoch(&expires
);
336 isc_interval_set(&interval
, 10, 0);
338 RUNTIME_CHECK(isc_timer_create(timgr
, isc_timertype_once
, &expires
,
339 &interval
, t1
, timeout
, so1
, &ti1
) ==
343 * Open up a socket that will connect to www.flame.org, port 80.
347 ina
.s_addr
= inet_addr("204.152.184.97");
348 if (0 && pf
== PF_INET6
)
349 isc_sockaddr_v6fromin(&sockaddr
, &ina
, 80);
351 isc_sockaddr_fromin(&sockaddr
, &ina
, 80);
352 RUNTIME_CHECK(isc_socket_create(socketmgr
, isc_sockaddr_pf(&sockaddr
),
354 &so2
) == ISC_R_SUCCESS
);
356 RUNTIME_CHECK(isc_socket_connect(so2
, &sockaddr
, t2
,
357 my_connect
, "so2") == ISC_R_SUCCESS
);
360 * Detaching these is safe, since the socket will attach to the
361 * task for any outstanding requests.
363 isc_task_detach(&t1
);
364 isc_task_detach(&t2
);
367 * Wait a short while.
371 fprintf(stderr
, "Destroying socket manager\n");
372 isc_socketmgr_destroy(&socketmgr
);
374 fprintf(stderr
, "Destroying timer manager\n");
375 isc_timermgr_destroy(&timgr
);
377 fprintf(stderr
, "Destroying task manager\n");
378 isc_taskmgr_destroy(&manager
);
380 isc_mem_stats(mctx
, stdout
);
381 isc_mem_destroy(&mctx
);