components/proftpd/patches/proftpd-retry.patch
changeset 1952 edbaa9c65514
parent 1343 a66d36656846
equal deleted inserted replaced
1951:da0722ff8ee6 1952:edbaa9c65514
     1 --- a/src/data.c
     1 --- a/src/data.c
     2 +++ b/src/data.c
     2 +++ b/src/data.c
     3 @@ -333,6 +333,7 @@ static int data_pasv_open(char *reason, off_t size) {
     3 @@ -337,6 +337,7 @@ static int data_pasv_open(char *reason, off_t size) {
     4  static int data_active_open(char *reason, off_t size) {
     4  static int data_active_open(char *reason, off_t size) {
     5    conn_t *c;
     5    conn_t *c;
     6    int rev;
     6    int bind_port, rev;
     7 +  int retries = 0;
     7 +  int retries = 0;
     8    pr_netaddr_t *bind_addr;
     8    pr_netaddr_t *bind_addr;
       
     9    unsigned char *root_revoke = NULL;
     9  
    10  
    10    if (!reason && session.xfer.filename)
    11 @@ -368,7 +369,9 @@ static int data_active_open(char *reason, off_t size) {
    11 @@ -348,45 +349,55 @@ static int data_active_open(char *reason, off_t size) {
    12      bind_port = INPORT_ANY;
    12      bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
       
    13    }
    13    }
    14  
    14  
    15 -  session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
    15 -  session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
    16 -    session.c->local_port-1, TRUE);
       
    17 +  for (;;) {
    16 +  for (;;) {
    18 +    session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
    17 +    session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port,
    19 +      session.c->local_port-1, TRUE);
    18 +      TRUE);
    20  
    19  
    21 -  /* Set the "stalled" timer, if any, to prevent the connection
    20    /* Default remote address to which to connect for an active transfer,
    22 -   * open from taking too long
    21     * if the client has not specified a different address via PORT/EPRT,
    23 -   */
    22 @@ -416,6 +419,15 @@ static int data_active_open(char *reason, off_t size) {
    24 -  if (timeout_stalled) {
    23  
    25 -    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
    24    if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
    26 -      "TimeoutStalled");
    25        session.data_port) == -1) {
    27 -  }
    26 +
    28 +    /* Set the "stalled" timer, if any, to prevent the connection
    27 +    if (session.d->xerrno == EADDRINUSE && retries < 16) {
    29 +     * open from taking too long
    28 +      destroy_pool(session.d->pool);
    30 +     */
    29 +      pr_signals_handle();
    31 +    if (timeout_stalled) {
    30 +      /* Wait up to MSL to avoid TIME_WAIT. */
    32 +      pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
    31 +      sleep(retries++);
    33 +        "TimeoutStalled");
    32 +      continue;
    34 +    }
    33 +    }
    35  
    34 +
    36 -  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
    35      pr_log_debug(DEBUG6,
    37 +    rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
    36        "Error connecting to %s#%u for active data transfer: %s",
    38  
    37        pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
    39 -  /* Protocol and socket options should be set before handshaking. */
    38 @@ -427,6 +439,9 @@ static int data_active_open(char *reason, off_t size) {
    40 +    /* Protocol and socket options should be set before handshaking. */
    39      destroy_pool(session.d->pool);
    41  
    40      session.d = NULL;
    42 -  if (session.xfer.direction == PR_NETIO_IO_RD) {
    41      return -1;
    43 -    pr_inet_set_socket_opts(session.d->pool, session.d,
    42 +  } else
    44 -      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
    43 +    break;
    45 +    if (session.xfer.direction == PR_NETIO_IO_RD) {
    44 +
    46 +      pr_inet_set_socket_opts(session.d->pool, session.d,
       
    47 +        (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
       
    48      
       
    49 -  } else {
       
    50 -    pr_inet_set_socket_opts(session.d->pool, session.d,
       
    51 -      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
       
    52 -  }
       
    53 +    } else {
       
    54 +      pr_inet_set_socket_opts(session.d->pool, session.d,
       
    55 +        0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
       
    56 +    }
       
    57  
       
    58 -  /* Make sure that the necessary socket options are set on the socket prior
       
    59 -   * to the call to connect(2).
       
    60 -   */
       
    61 -  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
       
    62 -    IPTOS_THROUGHPUT, 1);
       
    63 -  pr_inet_generate_socket_event("core.data-connect", main_server,
       
    64 -    session.d->local_addr, session.d->listen_fd);
       
    65 +    /* Make sure that the necessary socket options are set on the socket prior
       
    66 +     * to the call to connect(2).
       
    67 +     */
       
    68 +    pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
       
    69 +      IPTOS_THROUGHPUT, 1);
       
    70 +    pr_inet_generate_socket_event("core.data-connect", main_server,
       
    71 +      session.d->local_addr, session.d->listen_fd);
       
    72  
       
    73 -  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
       
    74 +    if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
       
    75        session.data_port) == -1) {
       
    76 -    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
       
    77 -      strerror(session.d->xerrno));
       
    78 -    destroy_pool(session.d->pool);
       
    79 -    session.d = NULL;
       
    80 -    return -1;
       
    81 +      if (session.d->xerrno == EADDRINUSE && retries < 16) {
       
    82 +        destroy_pool(session.d->pool);
       
    83 +        pr_signals_handle();
       
    84 +        /* Wait up to MSL to avoid TIME_WAIT. */
       
    85 +        sleep(retries++);
       
    86 +        continue;
       
    87 +      }
       
    88 +      pr_response_add_err(R_425, _("Unable to build data connection: %s"),
       
    89 +        strerror(session.d->xerrno));
       
    90 +      destroy_pool(session.d->pool);
       
    91 +      session.d = NULL;
       
    92 +      return -1;
       
    93 +    } else
       
    94 +      break;
       
    95    }
    45    }
    96  
    46  
    97    c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
    47    c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
    98 
    48