/* * Accept a new client connection. If multithreaded, this will come in on a worker thread dedicated to this connection. * This is called from the listen wait handler. */ int maAcceptConn(MprSocket *sock, MaServer *server, cchar *ip, int port) { MaHostAddress *address; MaHost *host; MaConn *conn; MprSocket *listenSock; MprHeap *arena; int rc; mprAssert(server); mprAssert(sock); mprAssert(ip); mprAssert(port > 0); rc = 0; listenSock = sock->listenSock; mprLog(server, 4, "New connection from %s:%d for %s:%d %s", ip, port, listenSock->ipAddr, listenSock->port, listenSock->sslSocket ? "(secure)" : ""); /* * Map the address onto a suitable host to initially serve the request initially until we can parse the Host header. */ address = (MaHostAddress*) maLookupHostAddress(server, listenSock->ipAddr, listenSock->port); if (address == 0 || (host = mprGetFirstItem(address->vhosts)) == 0) { mprError(server, "No host configured for request %s:%d", listenSock->ipAddr, listenSock->port); mprFree(sock); return 1; } arena = mprAllocHeap(host, "conn", 1, 0, NULL); if (arena == 0) { mprError(server, "Can't create connect arena object. Insufficient memory."); mprFree(sock); return 1; } conn = createConn(arena, host, sock, ip, port, address); if (conn == 0) { mprError(server, "Can't create connect object. Insufficient memory."); mprFree(sock); mprFree(arena); return 1; } conn->arena = arena; if (maAddConn(host, conn) < 0) { mprFree(sock); #if BLD_FEATURE_MULTITHREAD mprEnableSocketEvents(listenSock); #endif mprFree(arena); return 1; } mprSetSocketCallback(conn->sock, (MprSocketProc) ioEvent, conn, MPR_READABLE, MPR_NORMAL_PRIORITY); #if BLD_FEATURE_MULTITHREAD mprEnableSocketEvents(listenSock); #endif return rc; }
PUBLIC void httpSetupWaitHandler(HttpConn *conn, int eventMask) { MprSocket *sp; sp = conn->sock; if (eventMask) { if (sp->handler == 0) { mprAddSocketHandler(sp, eventMask, conn->dispatcher, conn->ioCallback, conn, 0); } else { mprSetSocketDispatcher(sp, conn->dispatcher); mprEnableSocketEvents(sp, eventMask); } } else if (sp->handler) { mprWaitOn(sp->handler, eventMask); } }
/* Accept a new client connection on a new socket. If multithreaded, this will come in on a worker thread dedicated to this connection. This is called from the listen wait handler. */ HttpConn *httpAcceptConn(HttpEndpoint *endpoint, MprEvent *event) { HttpConn *conn; MprSocket *sock; MprDispatcher *dispatcher; MprEvent e; int level; mprAssert(endpoint); mprAssert(event); /* This will block in sync mode until a connection arrives */ if ((sock = mprAcceptSocket(endpoint->sock)) == 0) { if (endpoint->sock->handler) { mprEnableSocketEvents(endpoint->sock, MPR_READABLE); } return 0; } if (endpoint->ssl) { if (mprUpgradeSocket(sock, endpoint->ssl, 1) < 0) { mprCloseSocket(sock, 0); return 0; } } if (endpoint->sock->handler) { /* Re-enable events on the listen socket */ mprEnableSocketEvents(endpoint->sock, MPR_READABLE); } dispatcher = event->dispatcher; if (mprShouldDenyNewRequests()) { mprCloseSocket(sock, 0); return 0; } if ((conn = httpCreateConn(endpoint->http, endpoint, dispatcher)) == 0) { mprCloseSocket(sock, 0); return 0; } conn->notifier = endpoint->notifier; conn->async = endpoint->async; conn->endpoint = endpoint; conn->sock = sock; conn->port = sock->port; conn->ip = sclone(sock->ip); conn->secure = (endpoint->ssl != 0); if (!httpValidateLimits(endpoint, HTTP_VALIDATE_OPEN_CONN, conn)) { conn->endpoint = 0; httpDestroyConn(conn); return 0; } mprAssert(conn->state == HTTP_STATE_BEGIN); httpSetState(conn, HTTP_STATE_CONNECTED); if ((level = httpShouldTrace(conn, HTTP_TRACE_RX, HTTP_TRACE_CONN, NULL)) >= 0) { mprLog(level, "### Incoming connection from %s:%d to %s:%d %s", conn->ip, conn->port, sock->acceptIp, sock->acceptPort, conn->secure ? "(secure)" : ""); } e.mask = MPR_READABLE; e.timestamp = conn->http->now; (conn->ioCallback)(conn, &e); return conn; }