/* * function waitForMessage(timeout: Number = -1): Boolean */ static EjsVar *workerWaitForMessage(Ejs *ejs, EjsWorker *worker, int argc, EjsVar **argv) { MprTime mark, remaining; int timeout; timeout = (argc > 0) ? ejsGetInt(argv[0]): MAXINT; if (timeout < 0) { timeout = MAXINT; } mark = mprGetTime(ejs); do { if (mprServiceEvents(ejs->dispatcher, timeout, MPR_SERVICE_EVENTS | MPR_SERVICE_ONE_THING) > 0) { return (EjsVar*) ejs->trueValue; } remaining = mprGetRemainingTime(ejs, mark, timeout); } while (remaining > 0 && !mprIsExiting(ejs) && !ejs->exiting); return (EjsVar*) ejs->falseValue; }
EjsVar *ejsServiceEvents(Ejs *ejs, int count, int timeout, int flags) { MprTime mark, remaining; int rc; if (count < 0) { count = MAXINT; } if (timeout < 0) { timeout = MAXINT; } mark = mprGetTime(ejs); do { rc = mprServiceEvents(ejs->dispatcher, timeout, MPR_SERVICE_EVENTS | MPR_SERVICE_ONE_THING); if (rc > 0) { count -= rc; } remaining = mprGetRemainingTime(ejs, mark, timeout); } while (count > 0 && remaining > 0 && !mprIsExiting(ejs) && !ejs->exiting); return 0; }
/* * Sample main event loop. This demonstrates how to integrate Mpr with your * applications event loop using select() */ void eventLoop() { MSG msg; /* * If single threaded or if you desire control over the event loop, you * should code an event loop similar to that below: */ while (!mprIsExiting(mpr)) { // SetTimer(appHwnd, 0, till, NULL); /* * Socket events will be serviced in the msgProc */ if (GetMessage(&msg, NULL, 0, 0) == 0) { /* WM_QUIT received */ break; } TranslateMessage(&msg); DispatchMessage(&msg); } }
static void eventLoop() { int timeout, till; /* * We will nap for 50 milliseconds to avoid busy waiting */ timeout = 50; while (!mprIsExiting()) { if (mprRunTimers() > 0) { till = 0; } else { till = mprGetIdleTime(); } /* * This will run tasks if maxThreads == 0 (single threaded). If * multithreaded, the thread pool will run tasks */ if (mprRunTasks() > 0) { /* Returns > 0 if more work to do */ till = 0; } /* * Do some work here */ /* * Now service any pending I/O */ mprServiceEvents(1, min(timeout, till)); } }
MAIN(appweb, int argc, char **argv) { Mpr *mpr; MaHttp *http; cchar *ipAddrPort, *documentRoot, *argp, *logSpec; char *configFile, *ipAddr, *homeDir, *timeText, *ejsPrefix, *ejsPath, *changeRoot; int workers, outputVersion, argind, port; documentRoot = 0; changeRoot = ejsPrefix = ejsPath = 0; ipAddrPort = 0; ipAddr = 0; port = -1; logSpec = 0; server = 0; outputVersion = 0; workers = -1; configFile = BLD_FEATURE_CONFIG_FILE; homeDir = BLD_FEATURE_SERVER_ROOT; mpr = mprCreate(argc, argv, memoryFailure); argc = mpr->argc; argv = mpr->argv; #if BLD_FEATURE_ROMFS extern MprRomInode romFiles[]; mprSetRomFileSystem(mpr, romFiles); #endif if (osInit(mpr) < 0) { exit(2); } if (mprStart(mpr, 0) < 0) { mprUserError(mpr, "Can't start MPR for %s", mprGetAppName(mpr)); mprFree(mpr); return MPR_ERR_CANT_INITIALIZE; } for (argind = 1; argind < argc; argind++) { argp = argv[argind]; if (*argp != '-') { break; } if (strcmp(argp, "--config") == 0) { if (argind >= argc) { return printUsage(mpr); } configFile = argv[++argind]; #if BLD_UNIX_LIKE } else if (strcmp(argp, "--chroot") == 0) { if (argind >= argc) { return printUsage(mpr); } changeRoot = mprGetAbsPath(mpr, argv[++argind]); #endif } else if (strcmp(argp, "--debug") == 0 || strcmp(argp, "-D") == 0 || strcmp(argp, "-d") == 0 || strcmp(argp, "--debugger") == 0) { mprSetDebugMode(mpr, 1); } else if (strcmp(argp, "--ejs") == 0) { if (argind >= argc) { return printUsage(mpr); } ejsPrefix = mprStrdup(mpr, argv[++argind]); if ((ejsPath = strchr(ejsPrefix, ':')) != 0) { *ejsPath++ = '\0'; } ejsPath = mprGetAbsPath(mpr, ejsPath); } else if (strcmp(argp, "--home") == 0) { if (argind >= argc) { return printUsage(mpr); } homeDir = mprGetAbsPath(mpr, argv[++argind]); if (chdir((char*) homeDir) < 0) { mprPrintfError(mpr, "%s: Can't change directory to %s\n", mprGetAppName(mpr), homeDir); exit(2); } } else if (strcmp(argp, "--log") == 0 || strcmp(argp, "-l") == 0) { if (argind >= argc) { return printUsage(mpr); } logSpec = argv[++argind]; maStartLogging(mpr, logSpec); } else if (strcmp(argp, "--name") == 0 || strcmp(argp, "-n") == 0) { if (argind >= argc) { return printUsage(mpr); } mprSetAppName(mpr, argv[++argind], 0, 0); } else if (strcmp(argp, "--threads") == 0) { if (argind >= argc) { return printUsage(mpr); } workers = atoi(argv[++argind]); } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) { maStartLogging(mpr, "stdout:2"); } else if (strcmp(argp, "--version") == 0 || strcmp(argp, "-V") == 0) { outputVersion++; } else { mprPrintfError(mpr, "Unknown switch \"%s\"\n", argp); printUsage(mpr); exit(2); } } if (argc > argind) { if (argc > (argind + 2)) { return printUsage(mpr); } ipAddrPort = argv[argind++]; if (argc > argind) { documentRoot = argv[argind++]; } else { documentRoot = "."; } } if (outputVersion) { mprPrintf(mpr, "%s %s-%s\n", mprGetAppTitle(mpr), BLD_VERSION, BLD_NUMBER); exit(0); } if (ipAddrPort) { mprParseIp(mpr, ipAddrPort, &ipAddr, &port, MA_SERVER_DEFAULT_PORT_NUM); } else { #if BLD_FEATURE_CONFIG_PARSE if (configFile == 0) { configFile = mprStrcat(mpr, -1, mprGetAppName(mpr), ".conf", NULL); } if (!mprPathExists(mpr, configFile, R_OK)) { mprPrintfError(mpr, "Can't open config file %s\n", configFile); exit(2); } #else return printUsage(mpr); #endif #if !BLD_FEATURE_ROMFS if (homeDir == 0) { homeDir = mprGetPathParent(mpr, configFile); if (chdir((char*) homeDir) < 0) { mprPrintfError(mpr, "%s: Can't change directory to %s\n", mprGetAppName(mpr), homeDir); exit(2); } } #endif } homeDir = mprGetCurrentPath(mpr); if (checkEnvironment(mpr, argv[0], homeDir) < 0) { exit(3); } #if BLD_UNIX_LIKE if (changeRoot) { homeDir = mprGetAbsPath(mpr, changeRoot); if (chdir(homeDir) < 0) { mprError(mpr, "%s: Can't change directory to %s", homeDir); exit(4); } if (chroot(homeDir) < 0) { if (errno == EPERM) { mprError(mpr, "%s: Must be super user to use the --chroot option", mprGetAppName(mpr)); } else { mprError(mpr, "%s: Can't change change root directory to %s, errno %d", mprGetAppName(mpr), homeDir, errno); } exit(5); } } #endif /* * Create the top level HTTP service and default HTTP server. Set the initial server root to "." */ http = maCreateHttp(mpr); if (http == 0) { mprUserError(mpr, "Can't create HTTP service for %s", mprGetAppName(mpr)); return MPR_ERR_CANT_INITIALIZE; } server = maCreateServer(http, "default", ".", 0, -1); if (server == 0) { mprUserError(mpr, "Can't create HTTP server for %s", mprGetAppName(mpr)); return MPR_ERR_CANT_INITIALIZE; } if (maConfigureServer(mpr, http, server, configFile, ipAddr, port, documentRoot) < 0) { /* mprUserError(mpr, "Can't configure the server, exiting."); */ exit(6); } if (mpr->ipAddr) { mprLog(mpr, 2, "Server IP address %s", mpr->ipAddr); } timeText = mprFormatLocalTime(mpr, mprGetTime(mpr)); mprLog(mpr, 1, "Started at %s", timeText); mprFree(timeText); #if BLD_FEATURE_EJS if (ejsPrefix) { createEjsAlias(mpr, http, server, ejsPrefix, ejsPath); } #endif #if BLD_FEATURE_MULTITHREAD if (workers >= 0) { mprSetMaxWorkers(http, workers); } #endif #if BLD_WIN_LIKE if (!ejsPrefix) { writePort(server->defaultHost); } #endif if (maStartHttp(http) < 0) { mprUserError(mpr, "Can't start HTTP service, exiting."); exit(7); } #if BLD_FEATURE_MULTITHREAD mprLog(mpr, 1, "HTTP services are ready with max %d worker threads", mprGetMaxWorkers(mpr)); #else mprLog(mpr, 1, "HTTP services are ready (single-threaded)"); #endif /* * Service I/O events until instructed to exit */ while (!mprIsExiting(mpr)) { mprServiceEvents(mpr->dispatcher, -1, MPR_SERVICE_EVENTS | MPR_SERVICE_IO); } /* * Signal a graceful shutdown */ mprLog(http, 1, "Exiting ..."); maStopHttp(http); mprLog(http, 1, "Exit complete"); #if VXWORKS if (mprStop(mpr)) { mprFree(mpr); } #endif return 0; }
static int doRequest(MprHttp *http, cchar *url, MprList *fields, MprList *files) { MprHttpResponse *resp; MprKeyValue *header; char buf[MPR_HTTP_BUFSIZE], seqBuf[16], *responseHeaders, *redirect; int64 contentLen; int code, next, count, bytes, transCount; mprAssert(url && *url); mprLog(http, MPR_DEBUG, "fetch: %s %s", method, url); /* * Send the request */ count = -1; transCount = 0; do { for (next = 0; (header = mprGetNextItem(headers, &next)) != 0; ) { mprSetHttpHeader(http, 0, header->key, header->value); } if (sequence) { static int next = 0; mprItoa(seqBuf, sizeof(seqBuf), next++, 10); mprSetHttpHeader(http, 1, "X-Http-Seq", seqBuf); } if (ranges) { mprSetHttpHeader(http, 1, "Range", ranges); } if (fields) { mprSetHttpHeader(http, 1, "Content-Type", "application/x-www-form-urlencoded"); } if (chunkSize) { mprSetHttpChunked(http, 1); } if (setContentLength(http, fields, files) < 0) { return MPR_ERR_CANT_OPEN; } if (mprStartHttpRequest(http, method, url) < 0) { mprError(http, "Can't process request for \"%s\". %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_OPEN; } /* * This program does not do full-duplex writes with reads. ie. if you have a request that sends and receives * data in parallel -- http will do the writes first then read the response. */ if (files || fields) { if (writeBody(http, fields, files) < 0) { mprError(http, "Can't write body data to \"%s\". %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_WRITE; } } else { if (chunkSize) { mprFinalizeHttpWriting(http); } mprWaitForHttpResponse(http, -1); } #if WIN _setmode(fileno(stdout), O_BINARY); #endif while ((bytes = mprReadHttp(http, buf, sizeof(buf))) > 0) { showOutput(http, buf, bytes); } mprWaitForHttp(http, MPR_HTTP_STATE_COMPLETE, -1); /* May not be complete if a disconnect occurs */ if (http->state >= MPR_HTTP_STATE_CONTENT) { if (mprNeedHttpRetry(http, &redirect)) { if (redirect) { url = resolveUrl(http, redirect); } count--; transCount++; continue; } break; } } while (++count < http->retries && transCount < 4 && !mprIsExiting(http)); if (count >= http->retries) { mprError(http, "http: failed \"%s\" request for %s after %d attempt(s)", method, url, count); return MPR_ERR_TOO_MANY; } if (mprIsExiting(http)) { return MPR_ERR_BAD_STATE; } /* * Request now complete */ code = mprGetHttpCode(http); contentLen = mprGetHttpContentLength(http); mprLog(http, 6, "Response code %d, content len %d", code, contentLen); if (http->response) { if (showCode) { mprPrintf(http, "%d\n", code); } if (showHeaders) { responseHeaders = mprGetHttpHeaders(http); resp = http->response; mprPrintf(http, "%s %d %s\n", resp->protocol, resp->code, resp->message); mprPrintf(http, "%s\n", responseHeaders); mprFree(responseHeaders); } } if (code < 0) { mprError(http, "Can't process request for \"%s\" %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_READ; } else if (code == 0 && http->protocolVersion == 0) { ; } else if (!(200 <= code && code <= 206) && !(301 <= code && code <= 304)) { if (!showCode) { mprError(http, "Can't process request for \"%s\" (%d) %s", url, code, mprGetHttpError(http)); return MPR_ERR_CANT_READ; } } lock(); if (verbose && noout) { trace(http, url, fetchCount, method, code, (int) contentLen); } unlock(); return 0; }
static void processThread(MprCtx ctx) { MprHttp *http; MprList *files; cchar *path; char *url; int next; http = mprCreateHttp(ctx); mprSetHttpTimeout(http, timeout); mprSetHttpFollowRedirects(http, !nofollow); if (chunkSize) { mprSetHttpChunked(http, 1); } if (httpVersion == 0) { mprSetHttpKeepAlive(http, 0); mprSetHttpProtocol(http, "HTTP/1.0"); } if (username) { if (password == 0 && !strchr(username, ':')) { password = getPassword(http); } mprSetHttpCredentials(http, username, password); } while (!mprIsExiting(http) && (success || continueOnErrors)) { if (singleStep) waitForUser(http); if (fileData && !upload) { for (next = 0; (path = mprGetNextItem(fileData, &next)) != 0; ) { if (target[strlen(target) - 1] == '/') { url = mprJoinPath(http, target, mprGetPathBase(http, path)); } else { url = target; } files = mprCreateList(http); mprAddItem(files, path); url = resolveUrl(http, url); if (verbose) { mprPrintf(http, "putting: %s to %s\n", path, url); } if (doRequest(http, url, formData, files) < 0) { success = 0; mprFree(files); mprFree(url); break; } mprFree(files); mprFree(url); } } else { url = resolveUrl(http, target); if (doRequest(http, url, formData, fileData) < 0) { success = 0; mprFree(url); break; } } if (iterationsComplete(http)) break; } mprFree(http); }