static isc_result_t control_accept (controllistener_t * listener) { isc_result_t result; result = isc_socket_accept (listener->sock, listener->task, control_newconn, listener); if (result != ISC_R_SUCCESS) UNEXPECTED_ERROR (__FILE__, __LINE__, "isc_socket_accept() failed: %s", isc_result_totext (result)); else listener->listening = ISC_TRUE; return (result); }
static void my_listen(isc_task_t *task, isc_event_t *event) { char *name = event->ev_arg; isc_socket_newconnev_t *dev; isc_region_t region; isc_socket_t *oldsock; isc_task_t *newtask; dev = (isc_socket_newconnev_t *)event; printf("newcon %s (task %p, oldsock %p, newsock %p, result %d)\n", name, task, event->ev_sender, dev->newsocket, dev->result); fflush(stdout); if (dev->result == ISC_R_SUCCESS) { /* * Queue another listen on this socket. */ RUNTIME_CHECK(isc_socket_accept(event->ev_sender, task, my_listen, event->ev_arg) == ISC_R_SUCCESS); region.base = isc_mem_get(mctx, 20); region.length = 20; /* * Create a new task for this socket, and queue up a * recv on it. */ newtask = NULL; RUNTIME_CHECK(isc_task_create(manager, 0, &newtask) == ISC_R_SUCCESS); isc_socket_recv(dev->newsocket, ®ion, 1, newtask, my_recv, event->ev_arg); isc_task_detach(&newtask); } else { printf("detaching from socket %p\n", event->ev_sender); oldsock = event->ev_sender; isc_socket_detach(&oldsock); isc_event_free(&event); isc_task_shutdown(task); return; } isc_event_free(&event); }
static void isc_httpd_accept(isc_task_t *task, isc_event_t *ev) { isc_result_t result; isc_httpdmgr_t *httpdmgr = ev->ev_arg; isc_httpd_t *httpd; isc_region_t r; isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev; isc_sockaddr_t peeraddr; ENTER("accept"); LOCK(&httpdmgr->lock); if (MSHUTTINGDOWN(httpdmgr)) { NOTICE("accept shutting down, goto out"); goto out; } if (nev->result == ISC_R_CANCELED) { NOTICE("accept canceled, goto out"); goto out; } if (nev->result != ISC_R_SUCCESS) { /* XXXMLG log failure */ NOTICE("accept returned failure, goto requeue"); goto requeue; } (void)isc_socket_getpeername(nev->newsocket, &peeraddr); if (httpdmgr->client_ok != NULL && !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) { isc_socket_detach(&nev->newsocket); goto requeue; } httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t)); if (httpd == NULL) { /* XXXMLG log failure */ NOTICE("accept failed to allocate memory, goto requeue"); isc_socket_detach(&nev->newsocket); goto requeue; } httpd->mgr = httpdmgr; ISC_LINK_INIT(httpd, link); ISC_LIST_APPEND(httpdmgr->running, httpd, link); ISC_HTTPD_SETRECV(httpd); httpd->sock = nev->newsocket; isc_socket_setname(httpd->sock, "httpd", NULL); httpd->flags = 0; /* * Initialize the buffer for our headers. */ httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW); if (httpd->headerdata == NULL) { isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t)); isc_socket_detach(&nev->newsocket); goto requeue; } httpd->headerlen = HTTP_SENDGROW; isc_buffer_init(&httpd->headerbuffer, httpd->headerdata, httpd->headerlen); ISC_LIST_INIT(httpd->bufflist); isc_buffer_initnull(&httpd->bodybuffer); reset_client(httpd); r.base = (unsigned char *)httpd->recvbuf; r.length = HTTP_RECVLEN - 1; result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone, httpd); /* FIXME!!! */ POST(result); NOTICE("accept queued recv on socket"); requeue: result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept, httpdmgr); if (result != ISC_R_SUCCESS) { /* XXXMLG what to do? Log failure... */ NOTICE("accept could not reaccept due to failure"); } out: UNLOCK(&httpdmgr->lock); httpdmgr_destroy(httpdmgr); isc_event_free(&ev); EXIT("accept"); }
isc_result_t isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, isc_httpdclientok_t *client_ok, isc_httpdondestroy_t *ondestroy, void *cb_arg, isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp) { isc_result_t result; isc_httpdmgr_t *httpd; REQUIRE(mctx != NULL); REQUIRE(sock != NULL); REQUIRE(task != NULL); REQUIRE(tmgr != NULL); REQUIRE(httpdp != NULL && *httpdp == NULL); httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t)); if (httpd == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&httpd->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t)); return (result); } httpd->mctx = NULL; isc_mem_attach(mctx, &httpd->mctx); httpd->sock = NULL; isc_socket_attach(sock, &httpd->sock); httpd->task = NULL; isc_task_attach(task, &httpd->task); httpd->timermgr = tmgr; /* XXXMLG no attach function? */ httpd->client_ok = client_ok; httpd->ondestroy = ondestroy; httpd->cb_arg = cb_arg; ISC_LIST_INIT(httpd->running); ISC_LIST_INIT(httpd->urls); /* XXXMLG ignore errors on isc_socket_listen() */ result = isc_socket_listen(sock, SOMAXCONN); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_listen() failed: %s", isc_result_totext(result)); goto cleanup; } (void)isc_socket_filter(sock, "httpready"); result = isc_socket_accept(sock, task, isc_httpd_accept, httpd); if (result != ISC_R_SUCCESS) goto cleanup; httpd->render_404 = render_404; httpd->render_500 = render_500; *httpdp = httpd; return (ISC_R_SUCCESS); cleanup: isc_task_detach(&httpd->task); isc_socket_detach(&httpd->sock); isc_mem_detach(&httpd->mctx); (void)isc_mutex_destroy(&httpd->lock); isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t)); return (result); }
int main(int argc, char *argv[]) { isc_task_t *t1, *t2; isc_timermgr_t *timgr; isc_time_t expires; isc_interval_t interval; isc_timer_t *ti1; unsigned int workers; isc_socketmgr_t *socketmgr; isc_socket_t *so1, *so2; isc_sockaddr_t sockaddr; struct in_addr ina; struct in6_addr in6a; isc_result_t result; int pf; if (argc > 1) workers = atoi(argv[1]); else workers = 2; printf("%d workers\n", workers); if (isc_net_probeipv6() == ISC_R_SUCCESS) pf = PF_INET6; else pf = PF_INET; /* * EVERYTHING needs a memory context. */ mctx = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); /* * The task manager is independent (other than memory context) */ manager = NULL; RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) == ISC_R_SUCCESS); /* * Timer manager depends only on the memory context as well. */ timgr = NULL; RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS); t1 = NULL; RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS); t2 = NULL; RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, "1") == ISC_R_SUCCESS); RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, "2") == ISC_R_SUCCESS); printf("task 1 = %p\n", t1); printf("task 2 = %p\n", t2); socketmgr = NULL; RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS); /* * Open up a listener socket. */ so1 = NULL; 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); result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS); RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS); /* * Queue up the first accept event. */ RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, "so1") == ISC_R_SUCCESS); isc_time_settoepoch(&expires); isc_interval_set(&interval, 10, 0); ti1 = NULL; RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires, &interval, t1, timeout, so1, &ti1) == ISC_R_SUCCESS); /* * Open up a socket that will connect to www.flame.org, port 80. * Why not. :) */ so2 = NULL; ina.s_addr = inet_addr("204.152.184.97"); if (0 && pf == PF_INET6) 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, &so2) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2, my_connect, "so2") == ISC_R_SUCCESS); /* * Detaching these is safe, since the socket will attach to the * task for any outstanding requests. */ isc_task_detach(&t1); isc_task_detach(&t2); /* * Wait a short while. */ sleep(10); fprintf(stderr, "Destroying socket manager\n"); isc_socketmgr_destroy(&socketmgr); fprintf(stderr, "Destroying timer manager\n"); isc_timermgr_destroy(&timgr); fprintf(stderr, "Destroying task manager\n"); isc_taskmgr_destroy(&manager); isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }