connection_exit.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
  6. connection_t *n_conn;
  7. char *colon;
  8. if(!memchr(cell->payload + TOPIC_HEADER_SIZE,0,cell->length - TOPIC_HEADER_SIZE)) {
  9. log(LOG_WARNING,"connection_exit_begin_conn(): topic begin cell has no \\0. Dropping.");
  10. return 0;
  11. }
  12. colon = strchr(cell->payload + TOPIC_HEADER_SIZE, ':');
  13. if(!colon) {
  14. log(LOG_WARNING,"connection_exit_begin_conn(): topic begin cell has no colon. Dropping.");
  15. return 0;
  16. }
  17. *colon = 0;
  18. if(!atoi(colon+1)) { /* bad port */
  19. log(LOG_DEBUG,"connection_exit_begin_conn(): topic begin cell has invalid port. Dropping.");
  20. return 0;
  21. }
  22. log(LOG_DEBUG,"connection_exit_begin_conn(): Creating new exit connection.");
  23. n_conn = connection_new(CONN_TYPE_EXIT);
  24. if(!n_conn) {
  25. log(LOG_DEBUG,"connection_exit_begin_conn(): connection_new failed. Dropping.");
  26. return 0;
  27. }
  28. cell->payload[0] = 0;
  29. n_conn->topic_id = ntohs(*(uint16_t *)(cell->payload+2));
  30. n_conn->address = strdup(cell->payload + TOPIC_HEADER_SIZE);
  31. n_conn->port = atoi(colon+1);
  32. n_conn->state = EXIT_CONN_STATE_RESOLVING;
  33. n_conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */
  34. n_conn->bandwidth = -1;
  35. n_conn->s = -1; /* not yet valid */
  36. n_conn->n_receive_topicwindow = TOPICWINDOW_START;
  37. n_conn->p_receive_topicwindow = TOPICWINDOW_START;
  38. if(connection_add(n_conn) < 0) { /* no space, forget it */
  39. log(LOG_DEBUG,"connection_exit_begin_conn(): connection_add failed. Dropping.");
  40. connection_free(n_conn);
  41. return 0;
  42. }
  43. /* add it into the linked list of topics on this circuit */
  44. n_conn->next_topic = circ->n_conn;
  45. circ->n_conn = n_conn;
  46. /* send it off to the gethostbyname farm */
  47. if(dns_resolve(n_conn) < 0) {
  48. log(LOG_DEBUG,"connection_exit_begin_conn(): Couldn't queue resolve request.");
  49. connection_remove(n_conn);
  50. connection_free(n_conn);
  51. return 0;
  52. }
  53. return 0;
  54. }
  55. int connection_exit_connect(connection_t *conn) {
  56. int s; /* for the new socket */
  57. struct sockaddr_in dest_addr;
  58. if(router_compare_to_exit_policy(conn) < 0) {
  59. log(LOG_INFO,"connection_exit_connect(): %s:%d failed exit policy. Closing.", conn->address, conn->port);
  60. return -1;
  61. }
  62. /* all the necessary info is here. Start the connect() */
  63. s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  64. if (s < 0) {
  65. log(LOG_ERR,"connection_exit_connect(): Error creating network socket.");
  66. return -1;
  67. }
  68. fcntl(s, F_SETFL, O_NONBLOCK); /* set s to non-blocking */
  69. memset((void *)&dest_addr,0,sizeof(dest_addr));
  70. dest_addr.sin_family = AF_INET;
  71. dest_addr.sin_port = htons(conn->port);
  72. dest_addr.sin_addr.s_addr = htonl(conn->addr);
  73. log(LOG_DEBUG,"connection_exit_connect(): Connecting to %s:%u.",conn->address,conn->port);
  74. if(connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
  75. if(errno != EINPROGRESS){
  76. /* yuck. kill it. */
  77. perror("connect");
  78. log(LOG_DEBUG,"connection_exit_connect(): Connect failed.");
  79. return -1;
  80. } else {
  81. /* it's in progress. set state appropriately and return. */
  82. conn->s = s;
  83. connection_set_poll_socket(conn);
  84. conn->state = EXIT_CONN_STATE_CONNECTING;
  85. log(LOG_DEBUG,"connection_exit_connect(): connect in progress, socket %d.",s);
  86. connection_watch_events(conn, POLLOUT | POLLIN);
  87. return 0;
  88. }
  89. }
  90. /* it succeeded. we're connected. */
  91. log(LOG_DEBUG,"connection_exit_connect(): Connection to %s:%u established.",conn->address,conn->port);
  92. conn->s = s;
  93. connection_set_poll_socket(conn);
  94. conn->state = EXIT_CONN_STATE_OPEN;
  95. if(connection_wants_to_flush(conn)) { /* in case there are any queued data cells */
  96. log(LOG_ERR,"connection_exit_connect(): tell roger: newly connected conn had data waiting!");
  97. // connection_start_writing(conn);
  98. }
  99. // connection_process_inbuf(conn);
  100. connection_watch_events(conn, POLLIN);
  101. /* also, deliver a 'connected' cell back through the circuit. */
  102. return connection_edge_send_command(conn, circuit_get_by_conn(conn), TOPIC_COMMAND_CONNECTED);
  103. }
  104. /*
  105. Local Variables:
  106. mode:c
  107. indent-tabs-mode:nil
  108. c-basic-offset:2
  109. End:
  110. */