command.c 7.2 KB

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