hibernate.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /**
  5. * \file hibernate.c
  6. * \brief Functions to close listeners, stop allowing new circuits,
  7. * etc in preparation for closing down or going dormant.
  8. **/
  9. /*
  10. hibernating, phase 1:
  11. - send destroy in response to create cells
  12. - send end (policy failed) in response to begin cells
  13. - close an OR conn when it has no circuits
  14. hibernating, phase 2:
  15. (entered when bandwidth hard limit reached)
  16. - close all OR/AP/exit conns)
  17. */
  18. #include "or.h"
  19. #define HIBERNATE_STATE_LIVE 1
  20. #define HIBERNATE_STATE_EXITING 2
  21. #define HIBERNATE_STATE_LOWBANDWIDTH 3
  22. #define HIBERNATE_STATE_DORMANT 4
  23. #define SHUTDOWN_WAIT_LENGTH 30 /* seconds */
  24. int hibernate_state = HIBERNATE_STATE_LIVE;
  25. time_t hibernate_timeout = 0;
  26. /** Returns 1 if the bandwidth soft limit has been reached, else 0. */
  27. static int hibernate_soft_limit_reached(void) {
  28. return 0;
  29. }
  30. /** Returns 1 if the bandwidth hard limit has been reached, else 0. */
  31. static int hibernate_hard_limit_reached(void) {
  32. return 0;
  33. }
  34. /** Return the time when we should stop being dormant. */
  35. static time_t hibernate_calc_wakeup_time(void) {
  36. return 0;
  37. }
  38. /** Called when we get a SIGINT, or when bandwidth soft limit
  39. * is reached. */
  40. static void hibernate_begin(int new_state) {
  41. connection_t *conn;
  42. if(hibernate_state == HIBERNATE_STATE_EXITING) {
  43. /* we've been called twice now. close immediately. */
  44. log(LOG_NOTICE,"Second sigint received; exiting now.");
  45. tor_cleanup();
  46. exit(0);
  47. }
  48. tor_assert(hibernate_state == HIBERNATE_STATE_LIVE);
  49. /* close listeners */
  50. while((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
  51. (conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
  52. (conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
  53. log_fn(LOG_INFO,"Closing listener type %d", conn->type);
  54. connection_mark_for_close(conn);
  55. }
  56. /* XXX kill intro point circs */
  57. /* XXX upload rendezvous service descriptors with no intro points */
  58. if(new_state == HIBERNATE_STATE_EXITING) {
  59. log(LOG_NOTICE,"Interrupt: will shut down in %d seconds. Interrupt again to exit now.", SHUTDOWN_WAIT_LENGTH);
  60. hibernate_timeout = time(NULL) + SHUTDOWN_WAIT_LENGTH;
  61. } else { /* soft limit reached */
  62. log_fn(LOG_NOTICE,"Bandwidth limit reached; beginning hibernation.");
  63. hibernate_timeout = hibernate_calc_wakeup_time();
  64. }
  65. hibernate_state = new_state;
  66. }
  67. /** Called when we've been hibernating and our timeout is reached. */
  68. static void hibernate_end(int new_state) {
  69. tor_assert(hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH ||
  70. hibernate_state == HIBERNATE_STATE_DORMANT);
  71. /* listeners will be relaunched in run_scheduled_events() in main.c */
  72. log_fn(LOG_NOTICE,"Hibernation period ended. Resuming normal activity.");
  73. hibernate_state = new_state;
  74. hibernate_timeout = 0; /* no longer hibernating */
  75. }
  76. /** A wrapper around hibernate_begin, for when we get SIGINT. */
  77. void hibernate_begin_shutdown(void) {
  78. hibernate_begin(HIBERNATE_STATE_EXITING);
  79. }
  80. /** A wrapper to expose whether we're hibernating. */
  81. int we_are_hibernating(void) {
  82. return hibernate_state != HIBERNATE_STATE_LIVE;
  83. }
  84. /** The big function. Consider our environment and decide if it's
  85. * time to start/stop hibernating.
  86. */
  87. void consider_hibernation(time_t now) {
  88. connection_t *conn;
  89. if (hibernate_state != HIBERNATE_STATE_LIVE)
  90. tor_assert(hibernate_timeout);
  91. if (hibernate_state == HIBERNATE_STATE_EXITING) {
  92. if(hibernate_timeout <= now) {
  93. log(LOG_NOTICE,"Clean shutdown finished. Exiting.");
  94. tor_cleanup();
  95. exit(0);
  96. }
  97. return; /* if exiting soon, don't worry about bandwidth limits */
  98. }
  99. if(hibernate_timeout && hibernate_timeout <= now) {
  100. /* we've been hibernating; time to wake up. */
  101. hibernate_end(HIBERNATE_STATE_LIVE);
  102. return;
  103. }
  104. /* else, see if it's time to start hibernating */
  105. if (hibernate_state == HIBERNATE_STATE_LIVE &&
  106. hibernate_soft_limit_reached()) {
  107. log_fn(LOG_NOTICE,"Bandwidth soft limit reached; commencing hibernation.");
  108. hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH);
  109. }
  110. if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH &&
  111. hibernate_hard_limit_reached()) {
  112. hibernate_state = HIBERNATE_STATE_DORMANT;
  113. log_fn(LOG_NOTICE,"Going dormant. Blowing away remaining connections.");
  114. /* Close all OR/AP/exit conns. Leave dir conns. */
  115. while((conn = connection_get_by_type(CONN_TYPE_OR)) ||
  116. (conn = connection_get_by_type(CONN_TYPE_AP)) ||
  117. (conn = connection_get_by_type(CONN_TYPE_EXIT))) {
  118. log_fn(LOG_INFO,"Closing conn type %d", conn->type);
  119. connection_mark_for_close(conn);
  120. }
  121. }
  122. }