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...");
void WServer::run() { if (start()) { waitForShutdown(); stop(); } }
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(); }
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(); }
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(); } }
int test_main( void ) { if ( ProcessorID() != 0 ) { _Bg_Sleep_Forever(); } showPersonality(); if ( ( fwext_getPersonality()->Kernel_Config.TraceConfig & TRACE_Verbose ) != 0 ) { dumpBeDRAM(); } waitForShutdown(); Terminate(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(); }
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(); }
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(); }
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(); }
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(); }
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()"
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()
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()"
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()
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()