/** Consider our environment and decide if it's time * to start/stop hibernating. */ void consider_hibernation(time_t now) { int accounting_enabled = get_options()->AccountingMax != 0; char buf[ISO_TIME_LEN+1]; /* If we're in 'exiting' mode, then we just shut down after the interval * elapses. */ if (hibernate_state == HIBERNATE_STATE_EXITING) { tor_assert(shutdown_time); if (shutdown_time <= now) { log_notice(LD_GENERAL, "Clean shutdown finished. Exiting."); tor_cleanup(); exit(0); } return; /* if exiting soon, don't worry about bandwidth limits */ } if (hibernate_state == HIBERNATE_STATE_DORMANT) { /* We've been hibernating because of bandwidth accounting. */ tor_assert(hibernate_end_time); if (hibernate_end_time > now && accounting_enabled) { /* If we're hibernating, don't wake up until it's time, regardless of * whether we're in a new interval. */ return ; } else { hibernate_end_time_elapsed(now); } } /* Else, we aren't hibernating. See if it's time to start hibernating, or to * go dormant. */ if (hibernate_state == HIBERNATE_STATE_LIVE) { if (hibernate_soft_limit_reached()) { log_notice(LD_ACCT, "Bandwidth soft limit reached; commencing hibernation."); hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH, now); } else if (accounting_enabled && now < interval_wakeup_time) { format_local_iso_time(buf,interval_wakeup_time); log_notice(LD_ACCT, "Commencing hibernation. We will wake up at %s local time.", buf); hibernate_go_dormant(now); } } if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) { if (!accounting_enabled) { hibernate_end_time_elapsed(now); } else if (hibernate_hard_limit_reached()) { hibernate_go_dormant(now); } else if (hibernate_end_time <= now) { /* The hibernation period ended while we were still in lowbandwidth.*/ hibernate_end_time_elapsed(now); } } }
/** Called when we get a SIGINT, or when bandwidth soft limit is * reached. Puts us into "loose hibernation": we don't accept new * connections, but we continue handling old ones. */ static void hibernate_begin(hibernate_state_t new_state, time_t now) { connection_t *conn; or_options_t *options = get_options(); if (new_state == HIBERNATE_STATE_EXITING && hibernate_state != HIBERNATE_STATE_LIVE) { log_notice(LD_GENERAL,"SIGINT received %s; exiting now.", hibernate_state == HIBERNATE_STATE_EXITING ? "a second time" : "while hibernating"); tor_cleanup(); exit(0); } /* close listeners. leave control listener(s). */ while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_DNS_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_AP_NATD_LISTENER)) || (conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) { log_info(LD_NET,"Closing listener type %d", conn->type); connection_mark_for_close(conn); } /* XXX kill intro point circs */ /* XXX upload rendezvous service descriptors with no intro points */ if (new_state == HIBERNATE_STATE_EXITING) { log_notice(LD_GENERAL,"Interrupt: will shut down in %d seconds. Interrupt " "again to exit now.", options->ShutdownWaitLength); shutdown_time = time(NULL) + options->ShutdownWaitLength; } else { /* soft limit reached */ hibernate_end_time = interval_end_time; } hibernate_state = new_state; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }
/** Main service entry point. Starts the service control dispatcher and waits * until the service status is set to SERVICE_STOPPED. */ static void nt_service_main(void) { SERVICE_TABLE_ENTRYA table[2]; DWORD result = 0; char *errmsg; nt_service_loadlibrary(); table[0].lpServiceName = (char*)GENSRV_SERVICENAME; table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)nt_service_body; table[1].lpServiceName = NULL; table[1].lpServiceProc = NULL; if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) { result = GetLastError(); errmsg = format_win32_error(result); printf("Service error %d : %s\n", (int) result, errmsg); tor_free(errmsg); if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { if (tor_init(backup_argc, backup_argv)) return; switch (get_options()->command) { case CMD_RUN_TOR: do_main_loop(); break; case CMD_LIST_FINGERPRINT: case CMD_HASH_PASSWORD: case CMD_VERIFY_CONFIG: case CMD_DUMP_CONFIG: case CMD_KEYGEN: case CMD_KEY_EXPIRATION: log_err(LD_CONFIG, "Unsupported command (--list-fingerprint, " "--hash-password, --keygen, --dump-config, --verify-config, " "or --key-expiration) in NT service."); break; case CMD_RUN_UNITTESTS: default: log_err(LD_CONFIG, "Illegal command number %d: internal error.", get_options()->command); } tor_cleanup(); } } }
/** Called when we get a SIGINT, or when bandwidth soft limit is * reached. Puts us into "loose hibernation": we don't accept new * connections, but we continue handling old ones. */ static void hibernate_begin(hibernate_state_t new_state, time_t now) { const or_options_t *options = get_options(); if (new_state == HIBERNATE_STATE_EXITING && hibernate_state != HIBERNATE_STATE_LIVE) { log_notice(LD_GENERAL,"SIGINT received %s; exiting now.", hibernate_state == HIBERNATE_STATE_EXITING ? "a second time" : "while hibernating"); tor_cleanup(); exit(0); } if (new_state == HIBERNATE_STATE_LOWBANDWIDTH && hibernate_state == HIBERNATE_STATE_LIVE) { soft_limit_hit_at = now; n_seconds_to_hit_soft_limit = n_seconds_active_in_interval; n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval, n_bytes_written_in_interval); } /* close listeners. leave control listener(s). */ connection_mark_all_noncontrol_listeners(); /* XXX kill intro point circs */ /* XXX upload rendezvous service descriptors with no intro points */ if (new_state == HIBERNATE_STATE_EXITING) { log_notice(LD_GENERAL,"Interrupt: we have stopped accepting new " "connections, and will shut down in %d seconds. Interrupt " "again to exit now.", options->ShutdownWaitLength); shutdown_time = time(NULL) + options->ShutdownWaitLength; } else { /* soft limit reached */ hibernate_end_time = interval_end_time; } hibernate_state = new_state; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }
/** Called when the service is started via the system's service control * manager. This calls tor_init() and starts the main event loop. If * tor_init() fails, the service will be stopped and exit code set to * NT_SERVICE_ERROR_TORINIT_FAILED. */ static void nt_service_body(int argc, char **argv) { int r; (void) argc; /* unused */ (void) argv; /* unused */ nt_service_loadlibrary(); service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwCurrentState = SERVICE_START_PENDING; service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; service_status.dwWin32ExitCode = 0; service_status.dwServiceSpecificExitCode = 0; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 1000; hStatus = service_fns.RegisterServiceCtrlHandlerA_fn(GENSRV_SERVICENAME, (LPHANDLER_FUNCTION) nt_service_control); if (hStatus == 0) { /* Failed to register the service control handler function */ return; } r = tor_init(backup_argc, backup_argv); if (r) { /* Failed to start the Tor service */ r = NT_SERVICE_ERROR_TORINIT_FAILED; service_status.dwCurrentState = SERVICE_STOPPED; service_status.dwWin32ExitCode = r; service_status.dwServiceSpecificExitCode = r; service_fns.SetServiceStatus_fn(hStatus, &service_status); return; } /* Set the service's status to SERVICE_RUNNING and start the main * event loop */ service_status.dwCurrentState = SERVICE_RUNNING; service_fns.SetServiceStatus_fn(hStatus, &service_status); set_main_thread(); do_main_loop(); tor_cleanup(); }
/** Main service entry point. Starts the service control dispatcher and waits * until the service status is set to SERVICE_STOPPED. */ static void nt_service_main(void) { SERVICE_TABLE_ENTRY table[2]; DWORD result = 0,thread_id; char *errmsg; nt_service_loadlibrary(); table[0].lpServiceName = (char*)GENSRV_SERVICENAME; table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body; table[1].lpServiceName = NULL; table[1].lpServiceProc = NULL; if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) { result = GetLastError(); errmsg = nt_strerror(result); printf("Service error %d : %s\n", (int) result, errmsg); LocalFree(errmsg); if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { if (tor_init(backup_argc, backup_argv) < 0) return; switch (get_options()->command) { case CMD_RUN_TOR: WaitForSingleObject(CreateThread(0,0,(LPTHREAD_START_ROUTINE)tor_thread,0,0,(LPDWORD)&thread_id),INFINITE); break; case CMD_LIST_FINGERPRINT: case CMD_HASH_PASSWORD: case CMD_VERIFY_CONFIG: log_err(LD_CONFIG,get_lang_str(LANG_LOG_NTMAIN_CMDLINE_UNSUPPORTED_COMMAND)); break; case CMD_RUN_UNITTESTS: default: log_err(LD_CONFIG,get_lang_str(LANG_LOG_NTMAIN_INTERNAL_ERROR),get_options()->command); } tor_cleanup(); } } }
void scalliontor_free(ScallionTor* stor) { tor_cleanup(); g_free(stor); }