/* Destroy a connection. This removes the connection from the list of connections. */ PUBLIC void httpDestroyConn(HttpConn *conn) { if (!conn->destroyed && !conn->borrowed) { HTTP_NOTIFY(conn, HTTP_EVENT_DESTROY, 0); if (httpServerConn(conn)) { httpMonitorEvent(conn, HTTP_COUNTER_ACTIVE_CONNECTIONS, -1); if (conn->activeRequest) { httpMonitorEvent(conn, HTTP_COUNTER_ACTIVE_REQUESTS, -1); conn->activeRequest = 0; } } httpRemoveConn(conn); conn->input = 0; if (conn->tx) { httpClosePipeline(conn); } if (conn->sock) { mprCloseSocket(conn->sock, 0); } if (conn->dispatcher && conn->dispatcher->flags & MPR_DISPATCHER_AUTO) { mprDestroyDispatcher(conn->dispatcher); } conn->destroyed = 1; } }
static void destroyDispatcherQueue(MprDispatcher *q) { MprDispatcher *dp, *next; for (dp = q->next; dp != q; dp = next) { next = dp->next; mprDestroyDispatcher(dp); if (next == dp->next) { break; } } }
/* Per-thread execution. Called for main thread and helper threads. */ static void threadMain(void *data, MprThread *tp) { ThreadData *td; HttpConn *conn; MprEvent e; td = tp->data; td->dispatcher = mprCreateDispatcher(tp->name, 0); td->conn = conn = httpCreateConn(app->http, NULL, td->dispatcher); /* Relay to processThread via the dispatcher. This serializes all activity on the conn->dispatcher */ e.mask = MPR_READABLE; e.data = tp; mprRelayEvent(conn->dispatcher, (MprEventProc) processThread, conn, &e); mprDestroyDispatcher(td->dispatcher); }
/* Per-thread execution. Called for main thread and helper threads. */ static void threadMain(void *data, MprThread *tp) { ThreadData *td; HttpConn *conn; cchar *path; char *url; int next, count; td = tp->data; /* Create and start a dispatcher. This ensures that all activity on the connection in this thread will be serialized with respect to all I/O events and httpProtocol work. This also ensures that I/O events will be handled by this thread from httpWait. */ td->dispatcher = mprCreateDispatcher(tp->name, 0); mprStartDispatcher(td->dispatcher); td->conn = conn = httpCreateConn(NULL, td->dispatcher); httpFollowRedirects(conn, !app->nofollow); httpSetTimeout(conn, app->timeout, app->timeout); if (strcmp(app->protocol, "HTTP/1.0") == 0) { httpSetKeepAliveCount(conn, 0); httpSetProtocol(conn, "HTTP/1.0"); } if (app->iterations == 1) { conn->limits->keepAliveMax = 0; } if (app->username) { if (app->password == 0 && !strchr(app->username, ':')) { app->password = getPassword(); } httpSetCredentials(conn, app->username, app->password, app->authType); } for (count = 0; count < app->iterations; count++) { if (mprShouldDenyNewRequests(conn)) { break; } if (!app->success && !app->continueOnErrors) { break; } if (app->singleStep) waitForUser(); if (app->files && !app->upload) { for (next = 0; (path = mprGetNextItem(app->files, &next)) != 0; ) { /* If URL ends with "/", assume it is a directory on the target and append each file name */ if (app->target[strlen(app->target) - 1] == '/') { url = mprJoinPath(app->target, mprGetPathBase(path)); } else { url = app->target; } app->requestFiles = mprCreateList(-1, MPR_LIST_STATIC_VALUES | MPR_LIST_STABLE); mprAddItem(app->requestFiles, path); td->url = url = resolveUrl(conn, url); if (app->verbose) { mprPrintf("putting: %s to %s\n", path, url); } if (doRequest(conn, url, app->requestFiles) < 0) { app->success = 0; break; } } } else { td->url = url = resolveUrl(conn, app->target); if (doRequest(conn, url, app->files) < 0) { app->success = 0; break; } } if (app->verbose > 1) { mprPrintf("."); } } httpDestroyConn(conn); mprDestroyDispatcher(conn->dispatcher); finishThread(tp); }