command.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. extern or_options_t options; /* command-line and config-file options */
  6. static void command_process_create_cell(cell_t *cell, connection_t *conn);
  7. static void command_process_created_cell(cell_t *cell, connection_t *conn);
  8. static void command_process_relay_cell(cell_t *cell, connection_t *conn);
  9. static void command_process_destroy_cell(cell_t *cell, connection_t *conn);
  10. static void command_time_process_cell(cell_t *cell, connection_t *conn,
  11. int *num, int *time,
  12. void (*func)(cell_t *, connection_t *)) {
  13. struct timeval start, end;
  14. long time_passed;
  15. *num += 1;
  16. my_gettimeofday(&start);
  17. (*func)(cell, conn);
  18. my_gettimeofday(&end);
  19. time_passed = tv_udiff(&start, &end) ;
  20. if (time_passed > 5000) { /* more than 5ms */
  21. log_fn(LOG_INFO,"That call just took %ld ms.",time_passed/1000);
  22. }
  23. *time += time_passed;
  24. }
  25. void command_process_cell(cell_t *cell, connection_t *conn) {
  26. static int num_create=0, num_created=0, num_relay=0, num_destroy=0;
  27. static int create_time=0, created_time=0, relay_time=0, destroy_time=0;
  28. static long current_second = 0; /* from previous calls to gettimeofday */
  29. struct timeval now;
  30. my_gettimeofday(&now);
  31. if(now.tv_sec > current_second) { /* the second has rolled over */
  32. /* print stats */
  33. log(LOG_INFO,"At end of second:");
  34. log(LOG_INFO,"Create: %d (%d ms)", num_create, create_time/1000);
  35. log(LOG_INFO,"Created: %d (%d ms)", num_created, created_time/1000);
  36. log(LOG_INFO,"Relay: %d (%d ms)", num_relay, relay_time/1000);
  37. log(LOG_INFO,"Destroy: %d (%d ms)", num_destroy, destroy_time/1000);
  38. /* zero out stats */
  39. num_create = num_created = num_relay = num_destroy = 0;
  40. create_time = created_time = relay_time = destroy_time = 0;
  41. /* remember which second it is, for next time */
  42. current_second = now.tv_sec;
  43. }
  44. switch(cell->command) {
  45. case CELL_PADDING:
  46. /* do nothing */
  47. break;
  48. case CELL_CREATE:
  49. command_time_process_cell(cell, conn, &num_create, &create_time,
  50. command_process_create_cell);
  51. break;
  52. case CELL_CREATED:
  53. command_time_process_cell(cell, conn, &num_created, &created_time,
  54. command_process_created_cell);
  55. break;
  56. case CELL_RELAY:
  57. command_time_process_cell(cell, conn, &num_relay, &relay_time,
  58. command_process_relay_cell);
  59. break;
  60. case CELL_DESTROY:
  61. command_time_process_cell(cell, conn, &num_destroy, &destroy_time,
  62. command_process_destroy_cell);
  63. break;
  64. default:
  65. log_fn(LOG_WARNING,"Cell of unknown type (%d) received. Dropping.", cell->command);
  66. break;
  67. }
  68. }
  69. static void command_process_create_cell(cell_t *cell, connection_t *conn) {
  70. circuit_t *circ;
  71. circ = circuit_get_by_aci_conn(cell->aci, conn);
  72. if(circ) {
  73. log_fn(LOG_WARNING,"received CREATE cell (aci %d) for known circ. Dropping.", cell->aci);
  74. return;
  75. }
  76. circ = circuit_new(cell->aci, conn);
  77. circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
  78. if(cell->length != DH_ONIONSKIN_LEN) {
  79. log_fn(LOG_WARNING,"Bad cell length %d. Dropping.", cell->length);
  80. circuit_close(circ);
  81. return;
  82. }
  83. memcpy(circ->onionskin,cell->payload,cell->length);
  84. /* hand it off to the cpuworkers, and then return */
  85. if(assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
  86. log_fn(LOG_WARNING,"Failed to hand off onionskin. Closing.");
  87. circuit_close(circ);
  88. return;
  89. }
  90. log_fn(LOG_INFO,"success: handed off onionskin.");
  91. }
  92. static void command_process_created_cell(cell_t *cell, connection_t *conn) {
  93. circuit_t *circ;
  94. cell_t newcell;
  95. circ = circuit_get_by_aci_conn(cell->aci, conn);
  96. if(!circ) {
  97. log_fn(LOG_INFO,"(aci %d) unknown circ (probably got a destroy earlier). Dropping.", cell->aci);
  98. return;
  99. }
  100. if(circ->n_aci != cell->aci) {
  101. log_fn(LOG_WARNING,"got created cell from OPward? Closing.");
  102. circuit_close(circ);
  103. return;
  104. }
  105. assert(cell->length == DH_KEY_LEN);
  106. if(circ->cpath) { /* we're the OP. Handshake this. */
  107. log_fn(LOG_DEBUG,"at OP. Finishing handshake.");
  108. if(circuit_finish_handshake(circ, cell->payload) < 0) {
  109. log_fn(LOG_WARNING,"circuit_finish_handshake failed.");
  110. circuit_close(circ);
  111. return;
  112. }
  113. log_fn(LOG_DEBUG,"Moving to next skin.");
  114. if(circuit_send_next_onion_skin(circ) < 0) {
  115. log_fn(LOG_WARNING,"circuit_send_next_onion_skin failed.");
  116. circuit_close(circ);
  117. return;
  118. }
  119. } else { /* pack it into an extended relay cell, and send it. */
  120. memset(&newcell, 0, sizeof(cell_t));
  121. newcell.command = CELL_RELAY;
  122. newcell.aci = circ->p_aci;
  123. SET_CELL_RELAY_COMMAND(newcell, RELAY_COMMAND_EXTENDED);
  124. SET_CELL_STREAM_ID(newcell, ZERO_STREAM);
  125. newcell.length = RELAY_HEADER_SIZE + cell->length;
  126. memcpy(newcell.payload+RELAY_HEADER_SIZE, cell->payload, DH_KEY_LEN);
  127. log_fn(LOG_INFO,"Converting created cell to extended relay cell, sending.");
  128. if(circuit_deliver_relay_cell(&newcell, circ, CELL_DIRECTION_IN, NULL) < 0) {
  129. log_fn(LOG_WARNING,"failed to deliver extended cell. Closing.");
  130. circuit_close(circ);
  131. return;
  132. }
  133. }
  134. }
  135. static void command_process_relay_cell(cell_t *cell, connection_t *conn) {
  136. circuit_t *circ;
  137. circ = circuit_get_by_aci_conn(cell->aci, conn);
  138. if(!circ) {
  139. log_fn(LOG_INFO,"unknown circuit %d. Dropping.", cell->aci);
  140. return;
  141. }
  142. if(circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
  143. log_fn(LOG_WARNING,"circuit in create_wait. Closing.");
  144. circuit_close(circ);
  145. return;
  146. }
  147. if(cell->aci == circ->p_aci) { /* it's an outgoing cell */
  148. cell->aci = circ->n_aci; /* switch it */
  149. if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_OUT, conn->cpath_layer) < 0) {
  150. log_fn(LOG_WARNING,"circuit_deliver_relay_cell (forward) failed. Closing.");
  151. circuit_close(circ);
  152. return;
  153. }
  154. } else { /* it's an ingoing cell */
  155. cell->aci = circ->p_aci; /* switch it */
  156. if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_IN, NULL) < 0) {
  157. log_fn(LOG_WARNING,"circuit_deliver_relay_cell (backward) failed. Closing.");
  158. circuit_close(circ);
  159. return;
  160. }
  161. }
  162. }
  163. static void command_process_destroy_cell(cell_t *cell, connection_t *conn) {
  164. circuit_t *circ;
  165. circ = circuit_get_by_aci_conn(cell->aci, conn);
  166. if(!circ) {
  167. log_fn(LOG_INFO,"unknown circuit %d. Dropping.", cell->aci);
  168. return;
  169. }
  170. log_fn(LOG_DEBUG,"Received for aci %d.",cell->aci);
  171. if(circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
  172. onion_pending_remove(circ);
  173. }
  174. if(cell->aci == circ->p_aci || circ->cpath) {
  175. /* either the destroy came from behind, or we're the AP */
  176. circ->p_conn = NULL;
  177. circuit_close(circ);
  178. } else { /* the destroy came from ahead */
  179. circ->n_conn = NULL;
  180. log_fn(LOG_DEBUG, "Delivering 'truncated' back.");
  181. connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED);
  182. }
  183. }
  184. /*
  185. Local Variables:
  186. mode:c
  187. indent-tabs-mode:nil
  188. c-basic-offset:2
  189. End:
  190. */