Пример #1
0
	debug_log(	LOG_DBG, "fetchMinerInfo(): target difficulty: %f (%0.2fM)", difficulty, difficulty/1000000); 
					
	if (difficulty > 0.0)
	{
		mi->summary.targetDifficulty = difficulty;
	}

	// --------------------------------
	// Update global miner info object.
	// --------------------------------
	updateMinerStats(mi);

} // end of fetchMinerInfo()

DWORD WINAPI minerApiThread( LPVOID lpParam )
{
	CGMConfig * _cfg = (CGMConfig *) lpParam;

	Miner_Info _minerInfo;

	DWORD waitInterval = _cfg->minerPollInterval*1000; // miliseconds	

	debug_log(LOG_SVR, "minerApiThread(): will poll miner (%s@%d) status every %d seconds", _minerHost, _minerPort, waitInterval/1000);

	resetMinerInfoObject(&_minerInfo);

	wait(waitInterval);

	while (waitForShutdown(1) == 0)  // while shutdown event is not set
	{
		debug_log(LOG_DBG, "minerApiThread(): woke up; checking miner status...");
Пример #2
0
void WServer::run()
{
  if (start()) {
    waitForShutdown();
    stop();
  }
}
Пример #3
0
void Service::start()
{
    try
    {
        sp_modules_->loadModules();

        observers_.notify(&IObserver::onServerPrepared);
        if (!isShutdown())
            run();
    }
    catch (exception& e)
    {
        shutdown_now = true;
        try
        {
            observers_.notify(&IObserver::onServerClosing);
            onShutdown();
        }
        catch (...)
        {
        }

        throw;
    }

    waitForShutdown();
}
Пример #4
0
void GroupMessagingService::run()
{
    routing_table_ =
            sg::Service::instance()->getModulesManager().getModuleInterface<common::RoutingTable>(
                    "routing");

    // stubs
    sg::Stubs stubs(getServiceType());

    boost::shared_ptr<sg::WorkersPool> login_pool =
            getWorkersPoolsManager().registerPool<sg::SingleThreadStrategy>("login");

    stubs.registerMethod<methods::MethodOpen>(login_pool);
    stubs.registerMethod<methods::MethodClose>(login_pool);
    stubs.registerMethod<methods::MethodDropGrp>(login_pool);
    stubs.registerMethod<methods::MethodDropMember>(login_pool);
    stubs.registerMethod<methods::MethodAddMember>(login_pool);
    stubs.registerMethod<methods::MethodSetMemberRoleLevel>();
    stubs.registerMethod<methods::MethodGetOnlineMembersCount>(sg::Stubs::MethodAccessAllowAll);
    stubs.registerMethod<methods::MethodSendGrpChatMsg>(sg::Stubs::MethodAccessAllowAll);
    stubs.registerMethod<methods::MethodAckGrpChatMsg>(sg::Stubs::MethodAccessAllowClient);
    stubs.registerMethod<methods::MethodSendGrpSysMsg>(sg::Stubs::MethodAccessAllowOtherDomain);
    stubs.registerMethod<methods::MethodAckGrpSysMsg>(sg::Stubs::MethodAccessAllowClient);

    getRoutingTable()->startRoutingT<sg::ConnectionHandler>(stubs);


    LOG(info, "\n\n====== server start ("
            << getServiceType() << "_" << getServiceNumber() << "@" << getServiceDomain()
            << ") ======\n\n");
    waitForShutdown();
}
Пример #5
0
void Initializer::requestShutdown(int retcode) {
  // Stop thrift services/clients/and their thread pools.
  kExitCode = retcode;
  if (std::this_thread::get_id() != kMainThreadId) {
    raise(SIGUSR1);
  } else {
    // The main thread is requesting a shutdown, meaning in almost every case
    // it is NOT waiting for a shutdown.
    // Exceptions include: tight request / wait in an exception handler or
    // custom signal handling.
    Dispatcher::stopServices();
    waitForShutdown();
  }
}
Пример #6
0
int test_main( void ) {

  if ( ProcessorID() != 0 ) {
    _Bg_Sleep_Forever();
  }

  showPersonality();

  if ( ( fwext_getPersonality()->Kernel_Config.TraceConfig & TRACE_Verbose ) != 0 ) {
      dumpBeDRAM();
  }

  waitForShutdown();
  Terminate(0);
}
Пример #7
0
void MessagesStorageService::run()
{
    // stubs
    sg::Stubs stubs(getServiceType(),
            getWorkersPoolsManager().registerPool<sg::UnorderedThreadPoolStrategy>("roam", 8));

    sg::Service::instance()->getModulesManager().getModuleInterface<common::RoutingTable>(
                        "routing")->startRoutingT<sg::ConnectionHandler>(
                        		stubs);


    LOG(info, "\n\n====== server start ("
            << getServiceType() << "_" << getServiceNumber() << "@" << getServiceDomain()
            << ") ======\n\n");
    waitForShutdown();
}
Пример #8
0
void SimulatorService::run()
{
    // push
    auto_ptr<base::net::FilterCreatorStrategyBase> push_ssl_filter;
    string push_pem_file = getProperties().getWithDef<string>("push.pem_file", "");
    push_ssl_filter.reset(new base::net::SSLFilterCreatorStrategy(push_pem_file)); 

    auto_ptr<base::net::HandlerCreatorStrategyBase> push_handler_creator;
    push_handler_creator.reset(new base::net::DefaultHandlerCreatorStrategyT<PushHandler>());

    base::net::Acceptor push_acceptor(getCommunicator().reactor(), base::net::OPT_NODELAY);
    push_acceptor.open(base::net::SockAddr(getProperties().get<string>("push.address")),
            -1, 
            auto_ptr<base::net::HandlerCreatorStrategyBase>(push_handler_creator.release()),
            push_ssl_filter);


    // feedback
    auto_ptr<base::net::FilterCreatorStrategyBase> fb_ssl_filter;
    string fb_pem_file = getProperties().getWithDef<string>("feedback.pem_file", "");
    fb_ssl_filter.reset(new base::net::SSLFilterCreatorStrategy(fb_pem_file)); 

    auto_ptr<base::net::HandlerCreatorStrategyBase> fb_handler_creator;
    fb_handler_creator.reset(new base::net::DefaultHandlerCreatorStrategyT<FeedbackHandler>());

    base::net::Acceptor fb_acceptor(getCommunicator().reactor(), base::net::OPT_NODELAY);
    fb_acceptor.open(base::net::SockAddr(getProperties().get<string>("feedback.address")),
            -1, 
            auto_ptr<base::net::HandlerCreatorStrategyBase>(fb_handler_creator.release()),
            fb_ssl_filter);

    LOG(info, "\n\n====== server start ("
            << getServiceType() << "_" << getServiceNumber() << "@" << getServiceDomain()                                                                                               
            << ") ======\n\n");
    waitForShutdown();
}
Пример #9
0
ExitCode _initAndListen(int listenPort) {
    Client::initThread("initandlisten");

    _initWireSpec();
    auto globalServiceContext = getGlobalServiceContext();

    globalServiceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    globalServiceContext->setOpObserver(stdx::make_unique<OpObserver>());

    DBDirectClientFactory::get(globalServiceContext)
        .registerImplementation([](OperationContext* txn) {
            return std::unique_ptr<DBClientBase>(new DBDirectClient(txn));
        });

    const repl::ReplSettings& replSettings = repl::getGlobalReplicationCoordinator()->getSettings();

    {
        ProcessId pid = ProcessId::getCurrent();
        LogstreamBuilder l = log(LogComponent::kControl);
        l << "MongoDB starting : pid=" << pid << " port=" << serverGlobalParams.port
          << " dbpath=" << storageGlobalParams.dbpath;
        if (replSettings.isMaster())
            l << " master=" << replSettings.isMaster();
        if (replSettings.isSlave())
            l << " slave=" << (int)replSettings.isSlave();

        const bool is32bit = sizeof(int*) == 4;
        l << (is32bit ? " 32" : " 64") << "-bit host=" << getHostNameCached() << endl;
    }

    DEV log(LogComponent::kControl) << "DEBUG build (which is slower)" << endl;

#if defined(_WIN32)
    VersionInfoInterface::instance().logTargetMinOS();
#endif

    logProcessDetails();

    checked_cast<ServiceContextMongoD*>(getGlobalServiceContext())->createLockFile();

    transport::TransportLayerLegacy::Options options;
    options.port = listenPort;
    options.ipList = serverGlobalParams.bind_ip;

    auto sep =
        stdx::make_unique<ServiceEntryPointMongod>(getGlobalServiceContext()->getTransportLayer());
    auto sepPtr = sep.get();

    getGlobalServiceContext()->setServiceEntryPoint(std::move(sep));

    // Create, start, and attach the TL
    auto transportLayer = stdx::make_unique<transport::TransportLayerLegacy>(options, sepPtr);
    auto res = transportLayer->setup();
    if (!res.isOK()) {
        error() << "Failed to set up listener: " << res;
        return EXIT_NET_ERROR;
    }

    std::shared_ptr<DbWebServer> dbWebServer;
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        dbWebServer.reset(new DbWebServer(serverGlobalParams.bind_ip,
                                          serverGlobalParams.port + 1000,
                                          getGlobalServiceContext(),
                                          new RestAdminAccess()));
        if (!dbWebServer->setupSockets()) {
            error() << "Failed to set up sockets for HTTP interface during startup.";
            return EXIT_NET_ERROR;
        }
    }

    getGlobalServiceContext()->initializeGlobalStorageEngine();

#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
    if (WiredTigerCustomizationHooks::get(getGlobalServiceContext())->restartRequired()) {
        exitCleanly(EXIT_CLEAN);
    }
#endif

    // Warn if we detect configurations for multiple registered storage engines in
    // the same configuration file/environment.
    if (serverGlobalParams.parsedOpts.hasField("storage")) {
        BSONElement storageElement = serverGlobalParams.parsedOpts.getField("storage");
        invariant(storageElement.isABSONObj());
        BSONObj storageParamsObj = storageElement.Obj();
        BSONObjIterator i = storageParamsObj.begin();
        while (i.more()) {
            BSONElement e = i.next();
            // Ignore if field name under "storage" matches current storage engine.
            if (storageGlobalParams.engine == e.fieldName()) {
                continue;
            }

            // Warn if field name matches non-active registered storage engine.
            if (getGlobalServiceContext()->isRegisteredStorageEngine(e.fieldName())) {
                warning() << "Detected configuration for non-active storage engine "
                          << e.fieldName() << " when current storage engine is "
                          << storageGlobalParams.engine;
            }
        }
    }

    if (!getGlobalServiceContext()->getGlobalStorageEngine()->getSnapshotManager()) {
        if (moe::startupOptionsParsed.count("replication.enableMajorityReadConcern") &&
            moe::startupOptionsParsed["replication.enableMajorityReadConcern"].as<bool>()) {
            // Note: we are intentionally only erroring if the user explicitly requested that we
            // enable majority read concern. We do not error if the they are implicitly enabled for
            // CSRS because a required step in the upgrade procedure can involve an mmapv1 node in
            // the CSRS in the REMOVED state. This is handled by the TopologyCoordinator.
            invariant(replSettings.isMajorityReadConcernEnabled());
            severe() << "Majority read concern requires a storage engine that supports"
                     << " snapshots, such as wiredTiger. " << storageGlobalParams.engine
                     << " does not support snapshots.";
            exitCleanly(EXIT_BADOPTIONS);
        }
    }

    logMongodStartupWarnings(storageGlobalParams, serverGlobalParams);

    {
        stringstream ss;
        ss << endl;
        ss << "*********************************************************************" << endl;
        ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
        ss << " Create this directory or give existing directory in --dbpath." << endl;
        ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
        ss << "*********************************************************************" << endl;
        uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
    }

    {
        stringstream ss;
        ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist";
        uassert(12590, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.repairpath));
    }

    // TODO:  This should go into a MONGO_INITIALIZER once we have figured out the correct
    // dependencies.
    if (snmpInit) {
        snmpInit();
    }

    if (!storageGlobalParams.readOnly) {
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    }

    if (mmapv1GlobalOptions.journalOptions & MMAPV1Options::JournalRecoverOnly)
        return EXIT_NET_ERROR;

    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
    }

    auto startupOpCtx = getGlobalServiceContext()->makeOperationContext(&cc());

    repairDatabasesAndCheckVersion(startupOpCtx.get());

    if (storageGlobalParams.upgrade) {
        log() << "finished checking dbs";
        exitCleanly(EXIT_CLEAN);
    }

    uassertStatusOK(getGlobalAuthorizationManager()->initialize(startupOpCtx.get()));

    /* this is for security on certain platforms (nonce generation) */
    srand((unsigned)(curTimeMicros64() ^ startupSrandTimer.micros()));

    // The snapshot thread provides historical collection level and lock statistics for use
    // by the web interface. Only needed when HTTP is enabled.
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        statsSnapshotThread.go();

        invariant(dbWebServer);
        stdx::thread web(stdx::bind(&webServerListenThread, dbWebServer));
        web.detach();
    }

#ifndef _WIN32
    mongo::signalForkSuccess();
#endif
    AuthorizationManager* globalAuthzManager = getGlobalAuthorizationManager();
    if (globalAuthzManager->shouldValidateAuthSchemaOnStartup()) {
        Status status = authindex::verifySystemIndexes(startupOpCtx.get());
        if (!status.isOK()) {
            log() << redact(status);
            exitCleanly(EXIT_NEED_UPGRADE);
        }

        // SERVER-14090: Verify that auth schema version is schemaVersion26Final.
        int foundSchemaVersion;
        status =
            globalAuthzManager->getAuthorizationVersion(startupOpCtx.get(), &foundSchemaVersion);
        if (!status.isOK()) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but startup could not verify schema version: " << status;
            exitCleanly(EXIT_NEED_UPGRADE);
        }
        if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but found " << foundSchemaVersion << ". In order to upgrade "
                  << "the auth schema, first downgrade MongoDB binaries to version "
                  << "2.6 and then run the authSchemaUpgrade command.";
            exitCleanly(EXIT_NEED_UPGRADE);
        }
    } else if (globalAuthzManager->isAuthEnabled()) {
        error() << "Auth must be disabled when starting without auth schema validation";
        exitCleanly(EXIT_BADOPTIONS);
    } else {
        // If authSchemaValidation is disabled and server is running without auth,
        // warn the user and continue startup without authSchema metadata checks.
        log() << startupWarningsLog;
        log() << "** WARNING: Startup auth schema validation checks are disabled for the "
                 "database."
              << startupWarningsLog;
        log() << "**          This mode should only be used to manually repair corrupted auth "
                 "data."
              << startupWarningsLog;
    }

    auto shardingInitialized =
        uassertStatusOK(ShardingState::get(startupOpCtx.get())
                            ->initializeShardingAwarenessIfNeeded(startupOpCtx.get()));
    if (shardingInitialized) {
        reloadShardRegistryUntilSuccess(startupOpCtx.get());
    }

    if (!storageGlobalParams.readOnly) {
        logStartup(startupOpCtx.get());

        startFTDC();

        getDeleter()->startWorkers();

        restartInProgressIndexesFromLastShutdown(startupOpCtx.get());

        if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
            // Note: For replica sets, ShardingStateRecovery happens on transition to primary.
            if (!repl::getGlobalReplicationCoordinator()->isReplEnabled()) {
                uassertStatusOK(ShardingStateRecovery::recover(startupOpCtx.get()));
            }
        } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
            uassertStatusOK(
                initializeGlobalShardingStateForMongod(startupOpCtx.get(),
                                                       ConnectionString::forLocal(),
                                                       kDistLockProcessIdForConfigServer));
            Balancer::create(startupOpCtx->getServiceContext());
        }

        repl::getGlobalReplicationCoordinator()->startup(startupOpCtx.get());

        const unsigned long long missingRepl =
            checkIfReplMissingFromCommandLine(startupOpCtx.get());
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset" << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and "
                  << " no other clients are connected." << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this."
                  << startupWarningsLog;
            log() << "**         ";
            log() << " For more info see http://dochub.mongodb.org/core/ttlcollections";
            log() << startupWarningsLog;
        } else {
            startTTLBackgroundJob();
        }

        if (!replSettings.usingReplSets() && !replSettings.isSlave() &&
            storageGlobalParams.engine != "devnull") {
            ScopedTransaction transaction(startupOpCtx.get(), MODE_X);
            Lock::GlobalWrite lk(startupOpCtx.get()->lockState());
            FeatureCompatibilityVersion::setIfCleanStartup(
                startupOpCtx.get(), repl::StorageInterface::get(getGlobalServiceContext()));
        }
    }

    startClientCursorMonitor();

    PeriodicTask::startRunningPeriodicTasks();

    // MessageServer::run will return when exit code closes its socket and we don't need the
    // operation context anymore
    startupOpCtx.reset();

    auto start = getGlobalServiceContext()->addAndStartTransportLayer(std::move(transportLayer));
    if (!start.isOK()) {
        error() << "Failed to start the listener: " << start.toString();
        return EXIT_NET_ERROR;
    }

    return waitForShutdown();
}
Пример #10
0
ExitCode _initAndListen(int listenPort) {
    Client::initThread("initandlisten");

    initWireSpec();
    auto serviceContext = getGlobalServiceContext();

    serviceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    auto opObserverRegistry = stdx::make_unique<OpObserverRegistry>();
    opObserverRegistry->addObserver(stdx::make_unique<OpObserverShardingImpl>());
    opObserverRegistry->addObserver(stdx::make_unique<UUIDCatalogObserver>());

    if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
        opObserverRegistry->addObserver(stdx::make_unique<ShardServerOpObserver>());
    } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
        opObserverRegistry->addObserver(stdx::make_unique<ConfigServerOpObserver>());
    }
    setupFreeMonitoringOpObserver(opObserverRegistry.get());


    serviceContext->setOpObserver(std::move(opObserverRegistry));

    DBDirectClientFactory::get(serviceContext).registerImplementation([](OperationContext* opCtx) {
        return std::unique_ptr<DBClientBase>(new DBDirectClient(opCtx));
    });

    const repl::ReplSettings& replSettings =
        repl::ReplicationCoordinator::get(serviceContext)->getSettings();

    {
        ProcessId pid = ProcessId::getCurrent();
        LogstreamBuilder l = log(LogComponent::kControl);
        l << "MongoDB starting : pid=" << pid << " port=" << serverGlobalParams.port
          << " dbpath=" << storageGlobalParams.dbpath;

        const bool is32bit = sizeof(int*) == 4;
        l << (is32bit ? " 32" : " 64") << "-bit host=" << getHostNameCached() << endl;
    }

    DEV log(LogComponent::kControl) << "DEBUG build (which is slower)" << endl;

#if defined(_WIN32)
    VersionInfoInterface::instance().logTargetMinOS();
#endif

    logProcessDetails();

    serviceContext->setServiceEntryPoint(
        stdx::make_unique<ServiceEntryPointMongod>(serviceContext));

    if (!storageGlobalParams.repair) {
        auto tl =
            transport::TransportLayerManager::createWithConfig(&serverGlobalParams, serviceContext);
        auto res = tl->setup();
        if (!res.isOK()) {
            error() << "Failed to set up listener: " << res;
            return EXIT_NET_ERROR;
        }
        serviceContext->setTransportLayer(std::move(tl));
    }

    // Set up the periodic runner for background job execution. This is required to be running
    // before the storage engine is initialized.
    auto runner = makePeriodicRunner(serviceContext);
    runner->startup();
    serviceContext->setPeriodicRunner(std::move(runner));

    initializeStorageEngine(serviceContext, StorageEngineInitFlags::kNone);

#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
    if (EncryptionHooks::get(serviceContext)->restartRequired()) {
        exitCleanly(EXIT_CLEAN);
    }
#endif

    // Warn if we detect configurations for multiple registered storage engines in the same
    // configuration file/environment.
    if (serverGlobalParams.parsedOpts.hasField("storage")) {
        BSONElement storageElement = serverGlobalParams.parsedOpts.getField("storage");
        invariant(storageElement.isABSONObj());
        for (auto&& e : storageElement.Obj()) {
            // Ignore if field name under "storage" matches current storage engine.
            if (storageGlobalParams.engine == e.fieldName()) {
                continue;
            }

            // Warn if field name matches non-active registered storage engine.
            if (isRegisteredStorageEngine(serviceContext, e.fieldName())) {
                warning() << "Detected configuration for non-active storage engine "
                          << e.fieldName() << " when current storage engine is "
                          << storageGlobalParams.engine;
            }
        }
    }

    // Disallow running a storage engine that doesn't support capped collections with --profile
    if (!serviceContext->getStorageEngine()->supportsCappedCollections() &&
        serverGlobalParams.defaultProfile != 0) {
        log() << "Running " << storageGlobalParams.engine << " with profiling is not supported. "
              << "Make sure you are not using --profile.";
        exitCleanly(EXIT_BADOPTIONS);
    }

    // Disallow running WiredTiger with --nojournal in a replica set
    if (storageGlobalParams.engine == "wiredTiger" && !storageGlobalParams.dur &&
        replSettings.usingReplSets()) {
        log() << "Running wiredTiger without journaling in a replica set is not "
              << "supported. Make sure you are not using --nojournal and that "
              << "storage.journal.enabled is not set to 'false'.";
        exitCleanly(EXIT_BADOPTIONS);
    }

    logMongodStartupWarnings(storageGlobalParams, serverGlobalParams, serviceContext);

#ifdef MONGO_CONFIG_SSL
    if (sslGlobalParams.sslAllowInvalidCertificates &&
        ((serverGlobalParams.clusterAuthMode.load() == ServerGlobalParams::ClusterAuthMode_x509) ||
         sequenceContains(saslGlobalParams.authenticationMechanisms, "MONGODB-X509"))) {
        log() << "** WARNING: While invalid X509 certificates may be used to" << startupWarningsLog;
        log() << "**          connect to this server, they will not be considered"
              << startupWarningsLog;
        log() << "**          permissible for authentication." << startupWarningsLog;
        log() << startupWarningsLog;
    }
#endif

    {
        std::stringstream ss;
        ss << endl;
        ss << "*********************************************************************" << endl;
        ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
        ss << " Create this directory or give existing directory in --dbpath." << endl;
        ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
        ss << "*********************************************************************" << endl;
        uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
    }

    initializeSNMP();

    if (!storageGlobalParams.readOnly) {
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    }

    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
    }

    auto startupOpCtx = serviceContext->makeOperationContext(&cc());

    bool canCallFCVSetIfCleanStartup =
        !storageGlobalParams.readOnly && (storageGlobalParams.engine != "devnull");
    if (canCallFCVSetIfCleanStartup && !replSettings.usingReplSets()) {
        Lock::GlobalWrite lk(startupOpCtx.get());
        FeatureCompatibilityVersion::setIfCleanStartup(startupOpCtx.get(),
                                                       repl::StorageInterface::get(serviceContext));
    }

    auto swNonLocalDatabases = repairDatabasesAndCheckVersion(startupOpCtx.get());
    if (!swNonLocalDatabases.isOK()) {
        // SERVER-31611 introduced a return value to `repairDatabasesAndCheckVersion`. Previously,
        // a failing condition would fassert. SERVER-31611 covers a case where the binary (3.6) is
        // refusing to start up because it refuses acknowledgement of FCV 3.2 and requires the
        // user to start up with an older binary. Thus shutting down the server must leave the
        // datafiles in a state that the older binary can start up. This requires going through a
        // clean shutdown.
        //
        // The invariant is *not* a statement that `repairDatabasesAndCheckVersion` must return
        // `MustDowngrade`. Instead, it is meant as a guardrail to protect future developers from
        // accidentally buying into this behavior. New errors that are returned from the method
        // may or may not want to go through a clean shutdown, and they likely won't want the
        // program to return an exit code of `EXIT_NEED_DOWNGRADE`.
        severe(LogComponent::kControl) << "** IMPORTANT: "
                                       << swNonLocalDatabases.getStatus().reason();
        invariant(swNonLocalDatabases == ErrorCodes::MustDowngrade);
        exitCleanly(EXIT_NEED_DOWNGRADE);
    }

    // Assert that the in-memory featureCompatibilityVersion parameter has been explicitly set. If
    // we are part of a replica set and are started up with no data files, we do not set the
    // featureCompatibilityVersion until a primary is chosen. For this case, we expect the in-memory
    // featureCompatibilityVersion parameter to still be uninitialized until after startup.
    if (canCallFCVSetIfCleanStartup &&
        (!replSettings.usingReplSets() || swNonLocalDatabases.getValue())) {
        invariant(serverGlobalParams.featureCompatibility.isVersionInitialized());
    }

    if (storageGlobalParams.upgrade) {
        log() << "finished checking dbs";
        exitCleanly(EXIT_CLEAN);
    }

    // Start up health log writer thread.
    HealthLog::get(startupOpCtx.get()).startup();

    auto const globalAuthzManager = AuthorizationManager::get(serviceContext);
    uassertStatusOK(globalAuthzManager->initialize(startupOpCtx.get()));

    // This is for security on certain platforms (nonce generation)
    srand((unsigned)(curTimeMicros64()) ^ (unsigned(uintptr_t(&startupOpCtx))));

    if (globalAuthzManager->shouldValidateAuthSchemaOnStartup()) {
        Status status = verifySystemIndexes(startupOpCtx.get());
        if (!status.isOK()) {
            log() << redact(status);
            if (status == ErrorCodes::AuthSchemaIncompatible) {
                exitCleanly(EXIT_NEED_UPGRADE);
            } else if (status == ErrorCodes::NotMaster) {
                // Try creating the indexes if we become master.  If we do not become master,
                // the master will create the indexes and we will replicate them.
            } else {
                quickExit(EXIT_FAILURE);
            }
        }

        // SERVER-14090: Verify that auth schema version is schemaVersion26Final.
        int foundSchemaVersion;
        status =
            globalAuthzManager->getAuthorizationVersion(startupOpCtx.get(), &foundSchemaVersion);
        if (!status.isOK()) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but startup could not verify schema version: " << status;
            log() << "To manually repair the 'authSchema' document in the admin.system.version "
                     "collection, start up with --setParameter "
                     "startupAuthSchemaValidation=false to disable validation.";
            exitCleanly(EXIT_NEED_UPGRADE);
        }

        if (foundSchemaVersion <= AuthorizationManager::schemaVersion26Final) {
            log() << "This server is using MONGODB-CR, an authentication mechanism which "
                  << "has been removed from MongoDB 4.0. In order to upgrade the auth schema, "
                  << "first downgrade MongoDB binaries to version 3.6 and then run the "
                  << "authSchemaUpgrade command. "
                  << "See http://dochub.mongodb.org/core/3.0-upgrade-to-scram-sha-1";
            exitCleanly(EXIT_NEED_UPGRADE);
        }
    } else if (globalAuthzManager->isAuthEnabled()) {
        error() << "Auth must be disabled when starting without auth schema validation";
        exitCleanly(EXIT_BADOPTIONS);
    } else {
        // If authSchemaValidation is disabled and server is running without auth,
        // warn the user and continue startup without authSchema metadata checks.
        log() << startupWarningsLog;
        log() << "** WARNING: Startup auth schema validation checks are disabled for the "
                 "database."
              << startupWarningsLog;
        log() << "**          This mode should only be used to manually repair corrupted auth "
                 "data."
              << startupWarningsLog;
    }

    // This function may take the global lock.
    auto shardingInitialized = ShardingInitializationMongoD::get(startupOpCtx.get())
                                   ->initializeShardingAwarenessIfNeeded(startupOpCtx.get());
    if (shardingInitialized) {
        waitForShardRegistryReload(startupOpCtx.get()).transitional_ignore();
    }

    auto storageEngine = serviceContext->getStorageEngine();
    invariant(storageEngine);
    BackupCursorHooks::initialize(serviceContext, storageEngine);

    if (!storageGlobalParams.readOnly) {

        if (storageEngine->supportsCappedCollections()) {
            logStartup(startupOpCtx.get());
        }

        startMongoDFTDC();

        startFreeMonitoring(serviceContext);

        restartInProgressIndexesFromLastShutdown(startupOpCtx.get());

        if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
            // Note: For replica sets, ShardingStateRecovery happens on transition to primary.
            if (!repl::ReplicationCoordinator::get(startupOpCtx.get())->isReplEnabled()) {
                if (ShardingState::get(startupOpCtx.get())->enabled()) {
                    uassertStatusOK(ShardingStateRecovery::recover(startupOpCtx.get()));
                }
            }
        } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
            initializeGlobalShardingStateForMongoD(startupOpCtx.get(),
                                                   ConnectionString::forLocal(),
                                                   kDistLockProcessIdForConfigServer);

            Balancer::create(startupOpCtx->getServiceContext());

            ShardingCatalogManager::create(
                startupOpCtx->getServiceContext(),
                makeShardingTaskExecutor(executor::makeNetworkInterface("AddShard-TaskExecutor")));

            Grid::get(startupOpCtx.get())->setShardingInitialized();
        } else if (replSettings.usingReplSets()) {  // standalone replica set
            auto keysCollectionClient = stdx::make_unique<KeysCollectionClientDirect>();
            auto keyManager = std::make_shared<KeysCollectionManager>(
                KeysCollectionManager::kKeyManagerPurposeString,
                std::move(keysCollectionClient),
                Seconds(KeysRotationIntervalSec));
            keyManager->startMonitoring(startupOpCtx->getServiceContext());

            LogicalTimeValidator::set(startupOpCtx->getServiceContext(),
                                      stdx::make_unique<LogicalTimeValidator>(keyManager));
        }

        repl::ReplicationCoordinator::get(startupOpCtx.get())->startup(startupOpCtx.get());
        const unsigned long long missingRepl =
            checkIfReplMissingFromCommandLine(startupOpCtx.get());
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset." << startupWarningsLog;
            log() << "**          Database contents may appear inconsistent with the oplog and may "
                     "appear to not contain"
                  << startupWarningsLog;
            log() << "**          writes that were visible when this node was running as part of a "
                     "replica set."
                  << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and no "
                     "other clients are connected."
                  << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this."
                  << startupWarningsLog;
            log() << "**         ";
            log() << " For more info see http://dochub.mongodb.org/core/ttlcollections";
            log() << startupWarningsLog;
        } else {
            startTTLBackgroundJob();
        }

        if (replSettings.usingReplSets() || !internalValidateFeaturesAsMaster) {
            serverGlobalParams.validateFeaturesAsMaster.store(false);
        }
    }

    startClientCursorMonitor();

    PeriodicTask::startRunningPeriodicTasks();

    SessionKiller::set(serviceContext,
                       std::make_shared<SessionKiller>(serviceContext, killSessionsLocal));

    // Start up a background task to periodically check for and kill expired transactions; and a
    // background task to periodically check for and decrease cache pressure by decreasing the
    // target size setting for the storage engine's window of available snapshots.
    //
    // Only do this on storage engines supporting snapshot reads, which hold resources we wish to
    // release periodically in order to avoid storage cache pressure build up.
    if (storageEngine->supportsReadConcernSnapshot()) {
        startPeriodicThreadToAbortExpiredTransactions(serviceContext);
        startPeriodicThreadToDecreaseSnapshotHistoryCachePressure(serviceContext);
    }

    // Set up the logical session cache
    LogicalSessionCacheServer kind = LogicalSessionCacheServer::kStandalone;
    if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
        kind = LogicalSessionCacheServer::kSharded;
    } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
        kind = LogicalSessionCacheServer::kConfigServer;
    } else if (replSettings.usingReplSets()) {
        kind = LogicalSessionCacheServer::kReplicaSet;
    }

    auto sessionCache = makeLogicalSessionCacheD(kind);
    LogicalSessionCache::set(serviceContext, std::move(sessionCache));

    // MessageServer::run will return when exit code closes its socket and we don't need the
    // operation context anymore
    startupOpCtx.reset();

    auto start = serviceContext->getServiceExecutor()->start();
    if (!start.isOK()) {
        error() << "Failed to start the service executor: " << start;
        return EXIT_NET_ERROR;
    }

    start = serviceContext->getServiceEntryPoint()->start();
    if (!start.isOK()) {
        error() << "Failed to start the service entry point: " << start;
        return EXIT_NET_ERROR;
    }

    if (!storageGlobalParams.repair) {
        start = serviceContext->getTransportLayer()->start();
        if (!start.isOK()) {
            error() << "Failed to start the listener: " << start.toString();
            return EXIT_NET_ERROR;
        }
    }

    serviceContext->notifyStartupComplete();

#ifndef _WIN32
    mongo::signalForkSuccess();
#else
    if (ntservice::shouldStartService()) {
        ntservice::reportStatus(SERVICE_RUNNING);
        log() << "Service running";
    }
#endif

    if (MONGO_FAIL_POINT(shutdownAtStartup)) {
        log() << "starting clean exit via failpoint";
        exitCleanly(EXIT_CLEAN);
    }

    MONGO_IDLE_THREAD_BLOCK;
    return waitForShutdown();
}
Пример #11
0
ExitCode runMongosServer(ServiceContext* serviceContext) {
    Client::initThread("mongosMain");
    printShardingVersionInfo(false);

    initWireSpec();

    serviceContext->setServiceEntryPoint(
        stdx::make_unique<ServiceEntryPointMongos>(serviceContext));

    auto tl =
        transport::TransportLayerManager::createWithConfig(&serverGlobalParams, serviceContext);
    auto res = tl->setup();
    if (!res.isOK()) {
        error() << "Failed to set up listener: " << res;
        return EXIT_NET_ERROR;
    }
    serviceContext->setTransportLayer(std::move(tl));

    auto unshardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>();
    unshardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(serviceContext));
    unshardedHookList->addHook(
        stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(serviceContext));
    // TODO SERVER-33053: readReplyMetadata is not called on hooks added through
    // ShardingConnectionHook with _shardedConnections=false, so this hook will not run for
    // connections using globalConnPool.
    unshardedHookList->addHook(stdx::make_unique<rpc::CommittedOpTimeMetadataHook>(serviceContext));

    // Add sharding hooks to both connection pools - ShardingConnectionHook includes auth hooks
    globalConnPool.addHook(new ShardingConnectionHook(false, std::move(unshardedHookList)));

    auto shardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>();
    shardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(serviceContext));
    shardedHookList->addHook(
        stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(serviceContext));
    shardedHookList->addHook(stdx::make_unique<rpc::CommittedOpTimeMetadataHook>(serviceContext));

    shardConnectionPool.addHook(new ShardingConnectionHook(true, std::move(shardedHookList)));

    // Hook up a Listener for changes from the ReplicaSetMonitor
    // This will last for the scope of this function. i.e. until shutdown finishes
    auto shardingRSCL =
        ReplicaSetMonitor::getNotifier().makeListener<ShardingReplicaSetChangeListener>(
            serviceContext);

    // Mongos connection pools already takes care of authenticating new connections so the
    // replica set connection shouldn't need to.
    DBClientReplicaSet::setAuthPooledSecondaryConn(false);

    if (getHostName().empty()) {
        quickExit(EXIT_BADOPTIONS);
    }

    auto opCtx = cc().makeOperationContext();

    auto logicalClock = stdx::make_unique<LogicalClock>(opCtx->getServiceContext());
    LogicalClock::set(opCtx->getServiceContext(), std::move(logicalClock));

    {
        Status status = initializeSharding(opCtx.get());
        if (!status.isOK()) {
            if (status == ErrorCodes::CallbackCanceled) {
                invariant(globalInShutdownDeprecated());
                log() << "Shutdown called before mongos finished starting up";
                return EXIT_CLEAN;
            }
            error() << "Error initializing sharding system: " << status;
            return EXIT_SHARDING_ERROR;
        }

        Grid::get(opCtx.get())
            ->getBalancerConfiguration()
            ->refreshAndCheck(opCtx.get())
            .transitional_ignore();
    }

    startMongoSFTDC();

    Status status = AuthorizationManager::get(serviceContext)->initialize(opCtx.get());
    if (!status.isOK()) {
        error() << "Initializing authorization data failed: " << status;
        return EXIT_SHARDING_ERROR;
    }

    // Construct the sharding uptime reporter after the startup parameters have been parsed in order
    // to ensure that it picks up the server port instead of reporting the default value.
    shardingUptimeReporter.emplace();
    shardingUptimeReporter->startPeriodicThread();

    clusterCursorCleanupJob.go();

    UserCacheInvalidator cacheInvalidatorThread(AuthorizationManager::get(serviceContext));
    {
        cacheInvalidatorThread.initialize(opCtx.get());
        cacheInvalidatorThread.go();
    }

    PeriodicTask::startRunningPeriodicTasks();

    // Set up the periodic runner for background job execution
    auto runner = makePeriodicRunner(serviceContext);
    runner->startup();
    serviceContext->setPeriodicRunner(std::move(runner));

    SessionKiller::set(serviceContext,
                       std::make_shared<SessionKiller>(serviceContext, killSessionsRemote));

    LogicalSessionCache::set(
        serviceContext,
        stdx::make_unique<LogicalSessionCacheImpl>(stdx::make_unique<ServiceLiaisonMongos>(),
                                                   stdx::make_unique<SessionsCollectionSharded>(),
                                                   RouterSessionCatalog::reapSessionsOlderThan));

    status = serviceContext->getServiceExecutor()->start();
    if (!status.isOK()) {
        error() << "Failed to start the service executor: " << redact(status);
        return EXIT_NET_ERROR;
    }

    status = serviceContext->getServiceEntryPoint()->start();
    if (!status.isOK()) {
        error() << "Failed to start the service entry point: " << redact(status);
        return EXIT_NET_ERROR;
    }

    status = serviceContext->getTransportLayer()->start();
    if (!status.isOK()) {
        error() << "Failed to start the transport layer: " << redact(status);
        return EXIT_NET_ERROR;
    }

    serviceContext->notifyStartupComplete();

#if !defined(_WIN32)
    signalForkSuccess();
#else
    if (ntservice::shouldStartService()) {
        ntservice::reportStatus(SERVICE_RUNNING);
        log() << "Service running";
    }
#endif

    // Block until shutdown.
    MONGO_IDLE_THREAD_BLOCK;
    return waitForShutdown();
}
Пример #12
0
int net_recvHttpLine(int sock, char * line, int maxLineLen, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	time_t start = 0;
	time_t end   = 0;

	char * p = line;

	time(&start);

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvHttpLine(): WSACreateEvent failed: %d", WSAGetLastError());			
		closesocket(sock);
		return SOCK_IO_ERROR;
	}

	while (index < maxLineLen) 
	{		
		recvBytes = 0;
		flags = 0;

		dataBuf.len = 1; 
	    dataBuf.buf = p;

wait_for_recv:  // submit the request

		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvHttpLine(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: // Wait for I/O completion

			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov: // Check the result of the I/O overlapped operation

			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvHttpLine(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvHttpLine(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		// Check what we received...

		if (*p == '\n')
		{
			p += recvBytes;
			index += recvBytes;
			break;
		} else
		{
			// Continue receiving the line until we get LF, we need to receive those bytes to cler the buffer.
			p += recvBytes;
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = p;
		}

		time(&end);
		if (end-start > timeout/1000)
		{
			debug_log(LOG_SVR, "net_recvHttpLine(): timeout waiting for LF character...");
			closesocket(sock);
			WSACloseEvent(recvOverlapped.hEvent);
			return SOCK_IO_ERROR;
		}

	} // while (index < maxLineLen) 

	WSACloseEvent(recvOverlapped.hEvent);

	if (index < maxLineLen)
		return SOCK_NO_ERROR;

	return SOCK_PROTOCOL_ERROR;
} // end of "net_recvHttpLine()" 
Пример #13
0
int net_recvBytes(int sock, char *buf, int bufSize, int * outLen, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) & recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) & dataBuf, sizeof (WSABUF));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvBytes(): WSACreateEvent failed: %d", WSAGetLastError());			
		return SOCK_IO_ERROR;
	}

	dataBuf.len = bufSize-1; // one for ending null
	dataBuf.buf = buf;

	*buf = '\0';
	while (index < bufSize) 
	{		
		recvBytes = 0;
		flags = 0;

wait_for_recv:
		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvBytes(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: 
			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov:
			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvBytes(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvBytes(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		if (recvBytes == 0)
			break;

		if ((index + (int) recvBytes) > bufSize)
			break;

		index += recvBytes;

		buf[index] = '\0';

		if ((bufSize-index) <= 0)
			break;

		dataBuf.len = bufSize-index;
		dataBuf.buf = buf+index;
	} // while (index < bufSize) 

	WSACloseEvent(recvOverlapped.hEvent);
	
	*outLen = index;

	return SOCK_NO_ERROR;
} // end of net_recvBytes()
Пример #14
0
int net_recvSmtpResponse(int sock, int * smtpCode, int timeout)
{
	WSAOVERLAPPED recvOverlapped;
	WSABUF dataBuf;

	DWORD recvBytes = 0;
	int index       = 0;
	DWORD flags     = 0;
	int rc          = 0;
	int lastError   = 0;

	int bytesLeft = SMTP_MAX_TEXT_LINE_LEN-1;
	int bufSize = SMTP_MAX_TEXT_LINE_LEN;

	char buf[SMTP_MAX_TEXT_LINE_LEN] = {0};
	char * p = NULL;

	// Make sure the RecvOverlapped struct is zeroed out
	SecureZeroMemory((PVOID) &recvOverlapped, sizeof (WSAOVERLAPPED));
	SecureZeroMemory((PVOID) &dataBuf, sizeof (WSABUF));
	SecureZeroMemory((PVOID) &buf, sizeof (buf));

	// Create an event handle and setup an overlapped structure.
	recvOverlapped.hEvent = WSACreateEvent();
	if (recvOverlapped.hEvent == NULL) 
	{
		debug_log(LOG_ERR, "net_recvSmtpResponse(): WSACreateEvent failed: %d", WSAGetLastError());	
		closesocket(sock);
		return SOCK_IO_ERROR;
	}

	while (index < bufSize) 
	{		
		recvBytes = 0;
		flags = 0;

		dataBuf.len = 1; 
	    dataBuf.buf = &buf[index];

wait_for_recv:  // submit the request

		rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
		if (rc != 0)
		{
			if (rc == SOCKET_ERROR) 
			{
				lastError = WSAGetLastError();

				if (lastError == WSAEWOULDBLOCK)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_recv;
				} else
				{
					if (lastError != WSA_IO_PENDING)
					{
						debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError);
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_IO_ERROR;					
					}
				}
			}

wait_for_io: // Wait for I/O completion

			rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
			if (rc == WSA_WAIT_TIMEOUT)
			{
				debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_TIMEOUT;
			}
			if (rc == WSA_WAIT_IO_COMPLETION) 
			{
				if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
				{
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_WDOG_SHUTDOWN;
				}

				SleepEx(SLEEP_EX_INTERVAL, TRUE);
				goto wait_for_io;
			}

wait_for_ov: // Check the result of the I/O overlapped operation

			rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
			if (rc == FALSE) 
			{
				lastError = WSAGetLastError();
				if (lastError == WSA_IO_INCOMPLETE)
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_ov;
				}

				debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError);
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}

			// ------------------------
			// Reset the signaled event
			// ------------------------
			rc = WSAResetEvent(recvOverlapped.hEvent);
			if (rc == FALSE) 
			{
				debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError());
				closesocket(sock);
				WSACloseEvent(recvOverlapped.hEvent);
				return SOCK_IO_ERROR;
			}
		}

		// Check what we received...

		if (buf[index] == '\r')
		{
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = &buf[index];

			// Receive another byte
wait_for_recv2:
			rc = WSARecv(sock, &dataBuf, 1, &recvBytes, &flags, &recvOverlapped, NULL);
			if (rc != 0)
			{
				if (rc == SOCKET_ERROR) 
				{
					lastError = WSAGetLastError();

					if (lastError == WSAEWOULDBLOCK)
					{
						if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
						{
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_WDOG_SHUTDOWN;
						}

						SleepEx(SLEEP_EX_INTERVAL, TRUE);
						goto wait_for_recv2;
					} else
					{
						if (lastError != WSA_IO_PENDING)
						{
							debug_log(LOG_ERR, "net_recvSmtpResponse(): WSARecv failed with error: %d", lastError);
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_IO_ERROR;					
						}
					}
				}
wait_for_io2: 
				rc = WSAWaitForMultipleEvents(1, &recvOverlapped.hEvent, TRUE, timeout, TRUE);
				if (rc == WSA_WAIT_TIMEOUT)
				{
					debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O timeout: %d", timeout);
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_TIMEOUT;
				}
				if (rc == WSA_WAIT_IO_COMPLETION) 
				{
					if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
					{
						closesocket(sock);
						WSACloseEvent(recvOverlapped.hEvent);
						return SOCK_WDOG_SHUTDOWN;
					}

					SleepEx(SLEEP_EX_INTERVAL, TRUE);
					goto wait_for_io2;
				}

wait_for_ov2:
				rc = WSAGetOverlappedResult(sock, &recvOverlapped, &recvBytes, FALSE, &flags);
				if (rc == FALSE) 
				{
					lastError = WSAGetLastError();
					if (lastError == WSA_IO_INCOMPLETE)
					{
						if (waitForShutdown(WAIT_FOR_SHUTDOWN_INTERVAL)) 
						{
							closesocket(sock);
							WSACloseEvent(recvOverlapped.hEvent);
							return SOCK_WDOG_SHUTDOWN;
						}

						SleepEx(SLEEP_EX_INTERVAL, TRUE);
						goto wait_for_ov2;
					}

					debug_log(LOG_ERR, "net_recvSmtpResponse(): overlapped I/O failed with error: %d", lastError);
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_IO_ERROR;
				}

				// ------------------------
				// Reset the signaled event
				// ------------------------
				rc = WSAResetEvent(recvOverlapped.hEvent);
				if (rc == FALSE) 
				{
					debug_log(LOG_ERR, "net_recvSmtpResponse(): WSAResetEvent failed with error = %d", WSAGetLastError());
					closesocket(sock);
					WSACloseEvent(recvOverlapped.hEvent);
					return SOCK_IO_ERROR;
				}
			}


			if ( buf[index] == '\n')
			{
				// we got to the end of line (CRLF found)
				index += recvBytes;

				if (buf[3] == '-')
				{
					net_recvSmtpResponse(sock, smtpCode, timeout); // receive another line in multiline replies
				} // endif 

				break;
			}
		} else
		{
			// Continue receiving the line until we get CRLF, we need to receive those bytes to cler the buffer.
			index += recvBytes;

			recvBytes = 0;
			flags = 0;

			dataBuf.len = 1; 
			dataBuf.buf = &buf[index];
		}

	} // while (index < bufSize) 

    buf[3] = 0; // get frist three bytes
    *smtpCode = atoi(buf);

	WSACloseEvent(recvOverlapped.hEvent);

	return SOCK_NO_ERROR;
} // end of "net_recvSmtpResponse()" 
Пример #15
0
int net_connectMX(char * domain, SOCKET * outSock)
{
   	struct  in_addr ipAddr;
	int retryCount = 0;
	unsigned long ip = 0;
	fd_set writeFD;
	struct timeval tm_out;
	SOCKET sock;
	struct sockaddr_in serv;
	int rc = 0;

	*outSock = INVALID_SOCKET;

	if (net_reQueryMxRecord(domain, &ipAddr) != SOCK_NO_ERROR)
	{
		debug_log(LOG_ERR, "net_connectMX(): re-querying of MX for domain: %s failed", domain);
		return SOCK_DNS_ERROR;
	}

	// Create a new socket 
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET) 
	{
		debug_log(LOG_ERR, "net_connectMX(): creating socket failed, rc: %d", WSAGetLastError());
		return SOCK_IO_ERROR;
	}

	if (net_setNonBlockingMode(sock) != SOCK_NO_ERROR)
	{
		debug_log(LOG_ERR, "net_connectMX(): putting socket into non-blocking mode failed");
		closesocket(sock);
		return SOCK_IO_ERROR;
	}
 
	memset(&serv, 0, sizeof(serv));
	serv.sin_family = AF_INET;
	serv.sin_port   = htons(25); // SMTP port 
	memcpy(&(serv.sin_addr), &ipAddr, sizeof(ipAddr));  // MX ip address
	//ip = inet_addr("127.0.0.1");
	//memcpy(&(serv.sin_addr), &ip, sizeof(ip));
	

	if (waitForShutdown(1)) 
	{
		closesocket(sock);
		return SOCK_WDOG_SHUTDOWN;
	}

	rc = connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr));
	if (rc == SOCKET_ERROR) 
	{
		rc = WSAGetLastError();

		if (rc == WSAEWOULDBLOCK)
		{
			if (waitForShutdown(1)) 
			{
				closesocket(sock);
				return SOCK_WDOG_SHUTDOWN;
			}

			FD_ZERO(&writeFD);
			FD_CLR(sock, &writeFD);
			FD_SET(sock, &writeFD);
			tm_out.tv_sec = SOCK_CONNECT_TIMEOUT;
			tm_out.tv_usec = 0;

			rc = select(0,  0, &writeFD, 0, &tm_out);
			if (rc == 0)
			{
				debug_log(LOG_SVR, "net_connectMX(): host \'%s\' did not respond in %d seconds", inet_ntoa(serv.sin_addr), SOCK_CONNECT_TIMEOUT);
				closesocket(sock);
				return SOCK_TIMEOUT;
			}

		} else
		{
			debug_log(LOG_SVR, "net_connectMX(): connect() to \'%s\' failed: %d", inet_ntoa(serv.sin_addr), rc);
			closesocket(sock);
			return SOCK_IO_ERROR;
		}
	}

	debug_log(LOG_INF, "net_connectMX(): successfully connected to: \'%s@25\'", inet_ntoa(serv.sin_addr));

	*outSock = sock;
	return SOCK_NO_ERROR;
} // end of net_connectMX()
Пример #16
0
int net_connect(char * host, int port, SOCKET * outSock, int localHost)
{
	int retryCount = 0;
	fd_set writeFD;
	struct timeval tm_out;
	SOCKET sock;
	struct sockaddr_in serv;
	int rc = 0;
	struct hostent *ip;

	*outSock = INVALID_SOCKET;

	ip = (struct hostent *) gethostbyname(host);

	if (ip == NULL)
	{
		debug_log(LOG_ERR, "net_connect(): gethostbyname(%s) failed: %d", host, WSAGetLastError());

		return SOCK_DNS_ERROR;
	}

	// Create a new socket 
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == INVALID_SOCKET) 
	{
		debug_log(LOG_ERR, "net_connect(): creating socket failed, rc: %d", WSAGetLastError());
		return SOCK_IO_ERROR;
	}

	if (net_setNonBlockingMode(sock) != SOCK_NO_ERROR)
	{
		debug_log(LOG_ERR, "net_connect(): putting socket into non-blocking mode failed");
		closesocket(sock);
		return SOCK_IO_ERROR;
	}
 
	memset(&serv, 0, sizeof(serv));
	serv.sin_family = AF_INET;
	serv.sin_addr = *((struct in_addr *)ip->h_addr);
	serv.sin_port = htons(port);
	

	if (waitForShutdown(1)) 
	{
		closesocket(sock);
		return SOCK_WDOG_SHUTDOWN;
	}

	rc = connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr));
	if (rc == SOCKET_ERROR) 
	{
		rc = WSAGetLastError();

		if (rc == WSAEWOULDBLOCK)
		{
			if (waitForShutdown(1)) 
			{
				closesocket(sock);
				return SOCK_WDOG_SHUTDOWN;
			}

			FD_ZERO(&writeFD);
			FD_CLR(sock, &writeFD);
			FD_SET(sock, &writeFD);
			if (localHost)
				tm_out.tv_sec = SOCK_LOCAL_CONNECT_TIMEOUT;
			else
				tm_out.tv_sec = SOCK_CONNECT_TIMEOUT;
			tm_out.tv_usec = 0;

			rc = select(0,  0, &writeFD, 0, &tm_out);

			if (rc == 0)
			{
				debug_log(LOG_SVR, "net_connect(): host \'%s\' (%s) did not respond in %d seconds", host, inet_ntoa(serv.sin_addr), localHost ? SOCK_LOCAL_CONNECT_TIMEOUT : SOCK_CONNECT_TIMEOUT);
				closesocket(sock);
				return SOCK_TIMEOUT;
			}

		} else
		{
			debug_log(LOG_SVR, "net_connect(): connect() to \'%s\' (%s) failed: %d", host, inet_ntoa(serv.sin_addr), rc);
			closesocket(sock);
			return SOCK_IO_ERROR;
		}
	}

	if (localHost == 0)
		debug_log(LOG_INF, "net_connect(): connected to: \'%s@%d\'", host, port);

	*outSock = sock;
	return SOCK_NO_ERROR;
} // end of net_connect()